poj1308 并查集

题意:和hdu1272差不多,只不过给出的是有向图,问图中的点是否是一颗树。

还是用并查集合并点,对于一条边,如果连接的两点已经在同一并查集内,则可以直接判否。合并时按边的方向记录点的入度,如果某个点入度大于1也就是某个点有多个父亲节点,则说明不是树。合并时顺便记录合并总次数,最后合并 点数-1 次则是树。

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 int fa[100005],num[100005];
 5 bool vi[100005];
 6 
 7 void init(){
 8     for(int i=1;i<=100004;i++)fa[i]=i;
 9 }
10 
11 int find(int x){
12     int r=x,t;
13     while(r!=fa[r])r=fa[r];
14     while(x!=r){
15         t=fa[x];
16         fa[x]=r;
17         x=t;
18     }
19     return r;
20 }
21 
22 int main(){
23     int a,b,c=0;
24     while(scanf("%d%d",&a,&b)!=EOF&&a!=-1||b!=-1){
25         printf("Case %d is ",++c);
26         if(a==0&&b==0){printf("a tree.
");continue;}
27         init();
28         memset(num,0,sizeof(num));
29         memset(vi,0,sizeof(vi));
30         bool f=1;
31         int x=find(a),y=find(b),cnt=0,ans=0;
32         if(!vi[a]){
33             cnt++;
34             vi[a]=1;
35         }
36         if(!vi[b]){
37             cnt++;
38             vi[b]=1;
39         }
40         num[b]++;
41         if(num[b]>1)f=0;
42         if(x!=y){
43             fa[x]=y;
44             ans++;
45         }
46         else f=0;
47         while(scanf("%d%d",&a,&b)&&a!=0||b!=0){
48             x=find(a),y=find(b);
49             if(!vi[a]){
50                 cnt++;
51                 vi[a]=1;
52             }
53             if(!vi[b]){
54                 cnt++;
55                 vi[b]=1;
56             }
57             num[b]++;
58             if(num[b]>1)f=0;
59             if(x!=y){
60                 fa[x]=y;
61                 ans++;
62             }
63             else f=0;
64         }
65         if(ans==cnt-1&&f)printf("a tree.
");
66         else printf("not a tree.
");
67     }
68     return 0;
69 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/4792985.html