经典的并查集问题
对于这种问题,并查集需要分类
开3*n的并查集,其中x用来连接与x同类的,x+n用来连接x吃的,x+2*n用来连接x被吃的。
1 x y时,如果 x吃y 或 x被y吃,那么为假话,
否则x与y同类,x吃的y也吃,x被吃的y也被吃;
2 x y时,如果 x与y同类(x与x自然也是同类) 或 y吃x,那么为假话,
否则x吃y,y被x吃,y吃x被吃的.
——代码
1 #include <cstdio> 2 #include <iostream> 3 #define N 1000001 4 5 int n, k, ans; 6 int f[N]; 7 8 inline int read() 9 { 10 int x = 0, f = 1; 11 char ch = getchar(); 12 for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1; 13 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘; 14 return x * f; 15 } 16 17 inline int find(int x) 18 { 19 return x == f[x] ? x : f[x] = find(f[x]); 20 } 21 22 inline void connect(int x, int y) 23 { 24 x = find(x); 25 y = find(y); 26 if(x ^ y) f[x] = y; 27 } 28 29 int main() 30 { 31 int i, j, x, y, z; 32 n = read(); 33 k = read(); 34 for(i = 1; i <= 3 * n; i++) f[i] = i; 35 for(i = 1; i <= k; i++) 36 { 37 z = read(); 38 x = read(); 39 y = read(); 40 if(x > n || y > n) 41 { 42 ans++; 43 continue; 44 } 45 if(z == 1) 46 { 47 if(find(x + n) == find(y) || find(x + 2 * n) == find(y)) 48 { 49 ans++; 50 continue; 51 } 52 connect(x, y); 53 connect(x + n, y + n); 54 connect(x + 2 * n, y + 2 * n); 55 } 56 else 57 { 58 if(find(x) == find(y) || find(x + 2 * n) == find(y)) 59 { 60 ans++; 61 continue; 62 } 63 connect(x + n, y); 64 connect(y + 2 * n, x); 65 connect(y + n, x + 2 * n); 66 } 67 } 68 printf("%d\n", ans); 69 return 0; 70 }
还有带权并查集的做法
正在努力学习。。
时间: 2024-10-21 04:18:28