hdu2874最近公共祖先问题

题目链接点击打开链接

Connections between cities

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12835    Accepted Submission(s): 2959


Problem Description
After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city. For most of roads had been totally destroyed during the war, there might be no path between two cities, no circle exists as well.
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.
 

Input
Input consists of multiple problem instances.For each instance, first line contains three integers n, m and c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n represents the number of cities numbered from 1 to n. Following m lines, each line has three integers i, j and k, represent a road between city i and city j, with length k. Last c lines, two integers i, j each line, indicates a query of city i and city j.
 

Output
For each problem instance, one line for each query. If no path between two cities, output “Not connected”, otherwise output the length of the shortest path between them.
 

Sample Input
 
   
5 3 21 3 22 4 35 2 31 44 5
 

Sample Output
 
   
Not connected6

这道题是不是树而是森林,需要DFS遍历森林里的每一颗树,用并查集来判定两个点是否在一棵树上,若不在

直接输出Not connected

AC代码:

#include
#include
#include
#include
#define maxn 20110
using namespace std;
int t;
int n,m,cnt;
int a,b,c;
struct node
{
    int s;
    int e;
    int w;
    int next;
}edge[maxn*2];
int head[maxn];
bool check[maxn];
int ver[maxn*2];//储存DFS序
int tot;//访问序号
int first[maxn];//每一个点第一次被访问的时候的位置
int dis[maxn];//每一点到根结点的距离
int depth[maxn*2];//第X位置的点的深度
int Min[maxn*2][20];
int father[maxn];
int find(int x)
{
   if(x!=father[x])
        father[x]=find(father[x]);
        return father[x];
}
void add(int s,int e,int w,int &k)
{
    edge[k].s=s;
    edge[k].e=e;
    edge[k].w=w;
    edge[k].next=head[s];
    head[s]=k++;
    swap(s,e);
    edge[k].s=s;
    edge[k].e=e;
    edge[k].w=w;
    edge[k].next=head[s];
    head[s]=k++;
}
void dfs(int u,int dep)
{
    check[u]=true;
    ver[++tot]=u;
    first[u]=tot;
    depth[tot]=dep;
    for(int k=head[u];k!=-1;k=edge[k].next)
    {
        int v=edge[k].e;
        int w=edge[k].w;
        if(!check[v])
        {
        dis[v]=dis[u]+w;
        dfs(v,dep+1);
        ver[++tot]=u;
        depth[tot]=dep;
        }
    }
}
void ST(int len)
{
    for(int i=1;i<=len;i++)
        Min[i][0]=i;
    for(int i=1;(1<y)
        swap(x,y);
    if(x==y)
        return ver[x];
    int temp=RMQ(x,y);
    return ver[temp];
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&cnt))
    {
        tot=0;
        for(int i=0;i<=n;i++)
            father[i]=i;
        memset(check,false,sizeof(check));
        memset(head,-1,sizeof(head));
        int num=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            int aa=find(a);
            int bb=find(b);
            if(aa!=bb)
                father[aa]=bb;
            add(a,b,c,num);
        }
        for(int i=1;i<=n;i++)
        {
        if(find(i)==i)
        {
        dis[i]=0;
        dfs(i,1);
        }
        }
        ST(2*n-1);
        int q1,q2;
        while(cnt--)
        {
            scanf("%d%d",&q1,&q2);
            if(find(q1)!=find(q2))
            {
                printf("Not connected\n");
                continue;
            }
            int temp=LCA(q1,q2);
            int ans=dis[q1]+dis[q2]-2*dis[temp];
            printf("%d\n",ans);
        }
    }
    return 0;
}


你可能感兴趣的:(C语言-ACM-算法-题解)