POJ 1308
http://poj.org/problem?id=1308
题意:判断这是不是一棵树。
思路:这个题还是有部分坑点的。首先空树也是一棵树,还有森林不是树。
关于森林的判断我是利用并查集把每一个点压缩路径,看一共有几个原始点,超过一个,则不是树是森林。
关于并查集
寻找以及压缩的代码
1 int Find(int x) 2 { 3 int _b,int _x=x; 4 while(belg[_x]!=_x) //压缩路径,找到它的最顶端的点。
5 { 6 _x=belg[_x]; 7 } 8 while(belg[x]!=x) //把这一系列的点的父亲节点都更新到最顶端的点。 9 { 10 _b=belg[x]; 11 belg[x]=_x; 12 x=_b; 13 } 14 return _x; 15 }
关于合并
1 int Union(int i,int j) 2 { 3 if(rand()&1) //随机分配 4 { 5 belg[j]=i; 6 } 7 else 8 { 9 belg[i]=j; 10 } 11 }
1 #include <string.h> 2 #include <stdio.h> 3 #include <iostream> 4 #define l 10010 5 6 using namespace std; 7 8 int belg[l]; 9 10 int fin(int x) 11 { 12 int _b,_x=x; 13 while(belg[_x]!=_x&&belg[_x]) 14 { 15 _x=belg[_x]; 16 } 17 while(belg[x]!=x&&belg[x]) 18 { 19 _b=belg[x]; 20 belg[x]=_x; 21 x=_b; 22 } 23 return _x; 24 } 25 26 int main() 27 { 28 // freopen("in.txt","r",stdin); 29 //freopen("out.txt","w",stdout); 30 int m,n,ans,cas,father; 31 bool mark[l]; 32 cas=0; 33 while(scanf("%d%d",&m,&n),m!=-1||n!=-1) 34 { 35 ans=1,father=0; 36 memset(belg,0,sizeof(belg)); 37 memset(mark,false,sizeof(mark)); 38 belg[n]=m; 39 mark[n]=true; 40 if(m==n&&m!=0) ans=0; 41 if(m==n&&m==0) ans=1; 42 else while(scanf("%d%d",&m,&n),m||n) 43 { 44 if(belg[m]==n) {ans=0;continue;} 45 if(belg[n]) ans=0; 46 if(n==m) ans=0; 47 if(!belg[n]&&n!=m) belg[n]=m; 48 fin(n); 49 mark[n]=true; 50 } 51 for(int i=0;i<100;i++) 52 if(mark[i]) fin(i); 53 for(int i=0;i<100;i++) 54 { 55 if(father==0&&mark[i]) {father=belg[i];continue;} 56 if(mark[i]&&belg[i]!=father) { 57 ans=0; 58 break; 59 } 60 } 61 if(ans) printf("Case %d is a tree.\n",++cas); 62 else printf("Case %d is not a tree.\n",++cas); 63 } 64 return 0; 65 }
测试数据:
1 2 2 3 3 1 5 6 0 0 0 0 0 0 1 2 3 4 4 5 5 3 0 0 2 1 3 1 4 1 5 1 0 0 2 1 3 1 4 1 0 0 1 2 4 5 5 4 0 0 1 2 1 3 1 4 1 5 0 0 -1 -1
答案
Case 1 is not a tree.
Case 2 is a tree.
Case 3 is a tree.
Case 4 is not a tree.
Case 5 is not a tree.
Case 6 is not a tree.
Case 7 is not a tree.
Case 8 is a tree.