标签:input 双向 输出 例子 技术分享 printf amp 集合 难度
是一道关于并查集的题目。
主要的思路是依次合并所有的结点,如果即将合并的两个结点已经属于同一集合,那么在它们合并之后必然会导致集合中的两个结点之间的通路不唯一!
需要注意的问题有:
1.例子中给出的图都是所有结点都连通的,但是实际输入中可能产生两个或两个以上的集合,所以需要判断。
2.结点的数字不是严格递增的,比如例子1中,数字7不存在。因此最好使用一个数字mark来标记数字是否出现过。
3.当一组数据的开始直接输入位0 0 ,应该认为是连通。输出"Yes".
1 #include <stdio.h> 2 #include <string.h> 3 #define N 100101 4 5 int Tree[N]; 6 bool mark[N]; 7 8 int findRoot(int x) 9 { 10 if(Tree[x]==-1) return x; 11 else{ 12 int tmp=findRoot(Tree[x]); 13 Tree[x]=tmp; 14 return tmp; 15 } 16 17 } 18 19 20 int main() 21 { 22 int a,b; 23 bool flag=false; 24 while(scanf("%d %d", &a, &b)!=EOF && a!=-1 && b!=-1) 25 { 26 27 if(a==0 && b==0) 28 { 29 printf("Yes\n"); 30 continue; 31 } 32 33 memset(mark, 0, sizeof(mark)); 34 memset(Tree, -1, sizeof(Tree)); 35 36 int max=-1,min=999999; 37 38 while(a||b) 39 { 40 if(a>max) max=a; 41 if(b>max) max=b; 42 if(a<min) min=a; 43 if(b<min) min=b; 44 45 mark[a]=mark[b]=true; 46 47 a=findRoot(a); 48 b=findRoot(b); 49 if(a!=b) 50 { 51 Tree[a]=b; 52 } 53 else{ 54 flag=true; //true 表示将出现多条路径 55 } 56 scanf("%d %d", &a, &b); 57 } 58 59 if(flag) 60 { 61 printf("No\n"); 62 } 63 64 else{ 65 int cnt=0; 66 for(int i=min; i<=max; i++) 67 { 68 if(Tree[i]==-1 && mark[i]) 69 cnt++; 70 } 71 if(cnt==1) 72 printf("Yes\n"); 73 else 74 printf("No\n"); 75 } 76 77 } 78 79 return 0; 80 }
说明:
while(a||b) { if(a>max) max=a; if(b>max) max=b; if(a<min) min=a; if(b<min) min=b;
max 与 min并不是必要的,只是为了在后续遍历中减少遍历的次数。
即代码段A可用代码段B代替
//代码段A
else{ int cnt=0; for(int i=min; i<=max; i++) { if(Tree[i]==-1 && mark[i]) cnt++; } if(cnt==1) printf("Yes\n"); else printf("No\n"); }
//代码段B
else{ int cnt=0; for(int i=1; i<N; i++) { if(Tree[i]==-1 && mark[i]) cnt++; } if(cnt==1) printf("Yes\n"); else printf("No\n"); }
标签:input 双向 输出 例子 技术分享 printf amp 集合 难度
原文地址:http://www.cnblogs.com/shenckicc/p/6801156.html