码迷,mamicode.com
首页 > 编程语言 > 详细

拓扑排序,树的直径模板(CF14D 枚举删边)

时间:2015-05-27 10:07:51      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:模板

HDU4607 树的直径

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define N 100005
#define INF 1<<30
int n,dis[N],E;
bool vis[N];
vector<int>G[N];
//注意点的标号是从0还是1开始的
int BFS(int x)
{
    int i;
    for(i=0;i<=n;i++)dis[i]=INF;
    memset(vis,0,sizeof(vis));
    queue<int>q;while(!q.empty())q.pop();

    q.push(x);
    dis[x]=0;
    while(!q.empty())
    {
        int u=q.front();q.pop();vis[u]=1;
        for(i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(dis[v]>dis[u]+1)
            {
                dis[v]=dis[u]+1;
                E=v;
                if(!vis[v])
                {
                    vis[v]=1;q.push(v);
                }
            }
        }
    }
    return E;
}
int main(){
    int T,i,que;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&que);
        for(i=0;i<=n;i++)G[i].clear();
        for(i=1;i<n;i++)
        {
            int a,b;scanf("%d %d",&a,&b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        E=BFS(1);
        E=BFS(E);
        while(que--)
        {
            int u;scanf("%d",&u);
            if(u<=dis[E]+1)printf("%d\n",u-1);
            else printf("%d\n",dis[E]+(u-(dis[E]+1))*2);//如果走过节点大于树直径上的点,要走回路(显然回路是走分支的部分,rt)直径+回路
        }
    }
    return 0;
}

Codeforces 14D Two Paths 树的直径

题意:给定一棵树
找2条点不重复的路径,使得两路径的长度乘积最大
思路:
1、为了保证点不重复,在图中删去一条边,枚举这条删边
2、这样得到了2个树,在各自的树中找最长链,即树的直径,然后相乘即可

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<set>
#include<vector>
#include<map>
#include<math.h>
#include<queue>
#include<string>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N 220
struct Edge {
    int from, to, nex;
    bool hehe;
}edge[N<<1];
int head[N], edgenum;
void add(int u, int v){
    Edge E={u,v,head[u],true};
    edge[edgenum] = E;
    head[u] = edgenum ++;
}
int n;
int dis[N];
void init(){ memset(head, -1, sizeof head); edgenum = 0; }
int bfs(int x){
    memset(dis, 0, sizeof dis);
    dis[x] = 1;
    queue<int>q; q.push(x);
    int hehe = x;
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(int i = head[u]; ~i; i = edge[i].nex) {
            if(!edge[i].hehe)continue;
            int v = edge[i].to;
            if(dis[v])continue;
            dis[v] = dis[u]+1, q.push(v);
            if(dis[hehe]<dis[v])hehe = v;
        }
    }
    return hehe;
}
int main(){
    int i, u, v;
    while(~scanf("%d",&n)){
        init();
        for(i=1;i<n;i++){
            scanf("%d %d",&u,&v);
            add(u,v); add(v,u);
        }
        int ans = 0;
        for(i = 0; i < edgenum; i+=2)
        {
            edge[i].hehe = edge[i^1].hehe = false;
            u = edge[i].from; v = edge[i].to;
            int L1 = bfs(u); int R1 = bfs(L1);
            int mul1 = dis[R1] -1;
            int L2 = bfs(v); int R2 = bfs(L2);
            int mul2 = dis[R2] -1;
            ans = max(ans, mul1 * mul2);
            edge[i].hehe = edge[i^1].hehe = true;
        }
        printf("%d\n",ans);
    }
    return 0;
}

拓扑排序

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include <queue>
using namespace std;
const int maxn=30;
int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x = 1;
        y = 0;
        return a;
    }
    int r = exgcd(b,a%b,x,y);
    int t = x;
    x = y;
    y = t - a/b*y;
    return r;
}


int head[maxn],ip,indegree[maxn];
int n,m,seq[maxn];

struct note
{
    int v,next;
} edge[maxn*maxn];

void init()
{
    memset(head,-1,sizeof(head));
    ip=0;
}

void addedge(int u,int v)
{
    edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}

int topo()///拓扑,可做模板
{
    queue<int>q;
    int indeg[maxn];
    for(int i=0; i<n; i++)
    {
        indeg[i]=indegree[i];
        if(indeg[i]==0)
            q.push(i);
    }
    int k=0;
    bool res=false;
    while(!q.empty())
    {
        if(q.size()!=1)res=true;
        int u=q.front();
        q.pop();
        seq[k++]=u;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            indeg[v]--;
            if(indeg[v]==0)
                q.push(v);
        }
    }
    if(k<n)return -1;///存在有向环,总之不能进行拓扑排序
    if(res)return 0;///可以进行拓扑排序,并且只有唯一一种方式,seq数组即是排序完好的序列
    return 1;///可以进行拓扑排序,有多种情况,seq数组是其中一种序列
}
int main(){
    int x,y;
    int r = exgcd(23,5,x,y);
    r = exgcd(23,5,x,y);
    printf("%d %d %d",r,x,y);
    return 0;
}

拓扑排序,树的直径模板(CF14D 枚举删边)

标签:模板

原文地址:http://blog.csdn.net/gg_gogoing/article/details/46041927

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!