题意:和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.\n");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.\n"); 66 else printf("not a tree.\n"); 67 } 68 return 0; 69 }
时间: 2024-10-24 12:48:32