http://poj.org/problem?id=1703
应该是书上例题(食物链 POJ1822)的简单版
这里同样用书上很巧妙的思路
如何表达 在集合A 和 集合B 中
并不是 让i.set = A 类似于这样活着P[i] = A
而是将 这个变成一个隐形条件 并且 不用再关心 i到底是在A集合 还是在B集合
建立并查集par[2*N]
让i 表示在集合A 中 i +N 表示在集合B 中
当两个数在同一集合(有共同根节点)时 说明这样的时间必然发生
及如果same(i, j+N) 则说明 i 在集合A中 j在集合B中 --->>>>i j 一定不再同一个集合中
这样简化问题 不再纠结于 i到底是在A 还是在B 而是针对问题 操作
注意不要用cin 会超时
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define N 100007 5 using namespace std; 6 7 int par[2*N]; 8 int rank[2*N]; 9 int find(int x) 10 { 11 if (x == par[x]) return x; 12 else return par[x] = find(par[x]); 13 } 14 15 void unite(int x, int y) 16 { 17 int px = find(x), py = find(y); 18 if (px == py) return ; 19 else if (rank[px] > rank[py]) 20 { 21 par[py] = px; 22 } 23 else 24 { 25 par[px] = py; 26 if (rank[px] == rank[py]) rank[py]++; 27 } 28 } 29 30 bool same(int x, int y) 31 { 32 int px = find(x), py = find(y); 33 return px == py; 34 } 35 int main() 36 { 37 int T, n, M; 38 freopen("in.txt", "r", stdin); 39 scanf("%d", &T); 40 while(T--) 41 { 42 scanf("%d%d", &n, &M); 43 for (int i = 1;i <= 2*n; i++) 44 { 45 par[i] = i; 46 rank[i] = 1; 47 } 48 char ch; 49 int a, b; 50 for (int i = 0; i < M; i++) 51 { 52 //cin >> ch;//用cin 读取 char 可以避免换行符 但是会超时 因为 输入规模比较大 53 getchar(); 54 scanf("%c", &ch); 55 scanf("%d%d", &a, &b); 56 if (ch == 'A') 57 { 58 if ( same(a, b) || same(a, b+n) ) 59 { 60 if ( same(a, b) ) printf("In the same gang. "); 61 else printf("In different gangs. "); 62 } 63 else printf("Not sure yet. "); 64 } 65 else 66 { 67 unite(a, b+n); 68 unite(a+n, b); 69 } 70 } 71 } 72 return 0; 73 }