并查集的基础题。在加入边前检查两点之前是否是同一个集合,若是则不是一棵树。输入完后检查是否所有点属于同一个集合。
1 #include<cstdio> 2 #include<string.h> 3 #include<iostream> 4 using namespace std; 5 const int maxn=1<<15; 6 bool flag,vis[maxn]; 7 int p[maxn],rank[maxn],data[maxn],m; 8 int a,b,ra,rb; 9 10 int find(int x) 11 { 12 if(x!=p[x]) 13 { 14 p[x]=find(p[x]); 15 } 16 return p[x]; 17 } 18 19 void unions(int x,int y) 20 { 21 if(rank[x]>rank[y]) 22 { 23 p[y]=x; 24 } 25 else 26 { 27 p[x]=y; 28 if(rank[x]==rank[y]) 29 rank[y]++; 30 } 31 } 32 int main() 33 { 34 //freopen("test.txt","r",stdin); 35 int t=0; 36 while(1) 37 { 38 flag=true; 39 m=0; 40 int i; 41 memset(vis,0,sizeof(vis)); 42 for(i=1;i<=maxn;i++) 43 { 44 p[i]=i; 45 rank[i]=0; 46 } 47 while(scanf("%d%d",&a,&b)!=EOF) 48 { 49 if(a==-1&&b==-1) return 0; 50 if(a==0&&b==0) 51 { 52 int key=find(data[0]); 53 for(i=1;i<m;i++) 54 { 55 if(key!=find(data[i])) 56 { 57 flag=false;break; 58 } 59 } 60 if(flag) 61 printf("Case %d is a tree.\n",++t); 62 else printf("Case %d is not a tree.\n",++t); 63 break; 64 } 65 if(!vis[a]) {data[m++]=a;vis[a]=true;} 66 if(!vis[b]) {data[m++]=b;vis[b]=true;} 67 if(!flag) continue; 68 ra=find(a); 69 rb=find(b); 70 if(ra==rb) {flag=false;continue;} 71 unions(ra,rb); 72 } 73 } 74 return 0; 75 }