题目描述:给定一个无向图,判断这个图是否满足任意两点之间有且仅有一条通路。
思路:并查集,若a和b之间有一条边且处于不同的集合中,则将a和b所在集合合并;若a和b本就在同一集合中(有一条通路),则加上这条a到b便有不止一条通路。另外还需要判断一下是否所有的点最后都能在一个集合中,即根的数量是否等于1.(其实说白了就是判断该图是不是一棵树)
注意:0 0的情况应该输出Yes(空树)
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 100007; 7 int f[N]; 8 bool mark[N]; 9 10 void init() 11 { 12 for ( int i = 1; i < N; i++ ) 13 { 14 mark[i] = false; 15 f[i] = i; 16 } 17 } 18 19 int find_f( int x ) 20 { 21 if ( f[x] != x ) f[x] = find_f(f[x]); 22 return f[x]; 23 } 24 25 void union_set( int x, int y ) 26 { 27 //f[x] = y居然会栈溢出 28 f[y] = x; 29 } 30 31 int main () 32 { 33 int a, b; 34 while ( 1 ) 35 { 36 scanf("%d%d", &a, &b); 37 if ( a == -1 && b == -1 ) break; 38 if ( a == 0 && b == 0 ) 39 { 40 printf("Yes "); 41 continue; 42 } 43 init(); 44 mark[a] = mark[b] = true; 45 union_set( a, b ); 46 bool flag = true; 47 while ( 1 ) 48 { 49 scanf("%d%d", &a, &b); 50 if ( a == 0 && b == 0 ) break; 51 if ( !flag ) continue; 52 mark[a] = mark[b] = true; 53 a = find_f(a), b = find_f(b); 54 if ( a == b ) flag = false; 55 else union_set( a, b ); 56 } 57 if ( !flag ) 58 { 59 printf("No "); 60 continue; 61 } 62 int cnt = 0; 63 for ( int i = 1; i < N; i++ ) 64 { 65 if ( mark[i] && f[i] == i ) cnt++; 66 } 67 if ( cnt == 1 ) printf("Yes "); 68 else printf("No "); 69 } 70 return 0; 71 }