标签:color eterm sequence collect unit nothing iostream display air
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 31092 | Accepted: 10549 |
Description
Input
Output
Sample Input
6 8 5 3 5 2 6 4 5 6 0 0 8 1 7 3 6 2 8 9 7 5 7 4 7 8 7 6 0 0 3 8 6 8 6 4 5 3 5 6 5 2 0 0 -1 -1
Sample Output
Case 1 is a tree. Case 2 is a tree. Case 3 is not a tree.
方法一:运用并查集,将有连接关系的点放入同一集合内,判断是否出现环和多个根。如果没有则为树。具体见代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<vector> 5 #include<cstring> 6 using namespace std; 7 struct edge 8 { 9 int s,t; 10 }E[1000]; 11 int par[1000],Rank[1000]; 12 int k=0,n=0,ne=0,num=0; 13 bool used[2000];//used用于记录1到出现的最大数字之间的数字是否使用过 14 void init(){ 15 memset(Rank,0,sizeof(Rank)); 16 for(int i=1;i<=1000;i++) 17 par[i]=i; 18 } 19 20 int Find(int i){ 21 if(par[i]==i)return i; 22 else return Find(par[i]); 23 } 24 bool same(int x,int y){ 25 return Find(x)==Find(y); 26 } 27 28 void unite(int x,int y){ 29 if(same(x,y))return; 30 else{ 31 x=Find(x); 32 y=Find(y); 33 if(Rank[x]<Rank[y]) 34 par[x]=y; 35 else{ 36 par[y]=x; 37 if(Rank[x]==Rank[y]) Rank[x]++; 38 } 39 } 40 } 41 void tree(){ 42 init(); 43 bool flag=true; 44 int now=-1; 45 for(int i=1;i<=n;i++){ 46 if(!same(E[i].s,E[i].t)){//判断是否首尾相连成环 47 unite(E[i].s,E[i].t); 48 } 49 else{ 50 flag=false; 51 break; 52 } 53 } 54 55 for(int i=1;i<=ne;i++){ 56 if(used[i]==true&&par[i]==i){//判断根的数目,如果多于1则不是树 57 num++; 58 if(num==2){ 59 flag=false; 60 break; 61 } 62 } 63 } 64 if(flag)printf("Case %d is a tree.\n",++k); 65 else printf("Case %d is not a tree.\n",++k); 66 } 67 68 int main(){ 69 int x,y; 70 while(scanf("%d%d",&x,&y)){ 71 if(x==-1&&y==-1) break; 72 else if(x!=0&&y!=0){ 73 ++n; 74 E[n].s=y; 75 E[n].t=x; 76 ne=max(x,max(ne,y)); 77 used[x]=true;//因为题目没有给出数目采用这种方法判断需要的循环次数 78 used[y]=true; 79 } 80 else{ 81 tree(); 82 memset(used,0,sizeof(used)); 83 init(); 84 n=0; 85 ne=0; 86 num=0; 87 } 88 } 89 return 0; 90 }
方法二:利用树的性质:(1)点数=边数+1,这个性质可以去掉多根的情况。(2)一个点最多有一个父节点,这个性质可以去掉成环的情况,具体代码如下:
1 #include<cstdio> 2 #include<cstring> 3 4 using namespace std; 5 6 int x,y,a[1000]={0},m,n,flag; 7 int main() 8 { 9 int k=1; 10 while(scanf("%d%d",&x,&y)) 11 { 12 if(x==-1&&y==-1) break; 13 m++;//输入一组边数+1 14 if(a[y]==2){flag=1;}//如果y已经作为过子节点,再一次做子节点,说明出现两个父节点(也可能是重复的边,也不是树),不是树 15 if(!a[x]&&x){a[x]=1;n++;}//1为父节点,2为子节点标记个点,点数+1 16 if(!a[y]&&y){a[y]=2;n++;} 17 if(x==0&&y==0) 18 { 19 if(!flag&&((n==m)||(n==0&&m==1))) printf("Case %d is a tree.\n",k++);//由于0 0也算入边内,因此m为边数+1,m==n;需特判空树 20 else printf("Case %d is not a tree.\n",k++); 21 m=0,n=0,flag=0; 22 memset(a,0,sizeof(a)); 23 } 24 } 25 return 0; 26 }
以上两种方法均可,代码都能AC,如有问题,还请指出,不胜感激。
标签:color eterm sequence collect unit nothing iostream display air
原文地址:http://www.cnblogs.com/acumtb16/p/6358086.html