并查集 食物链
https://www.luogu.org/problemnew/show/P2024
n(A)+n(B)+n(C)
两个点相连,代表两者是等效的(A<->B,若A成立,B也成立;若B成立,A也成立)。
一棵树上,如果有其中一个点成立,那么,树上的所有点也成立。
规定x+k*n,y+k*n代表x和y同类关系,x+k*n,y+(k+1)%3*n代表x吃y的关系。
1 x y
x,y same
如果x和y+n(或x和y+2*n)同属一棵树,那么代表x和y有吃(被吃)的关系,矛盾(这个跟A、B、C是没有任何相连,它只是代表着一种关系,如果x为A,那么y必为B(C),反映吃(被吃)的关系)
连(x,y)、(x+n,y+n)、(x+2*n,y+2*n)
2 x y
x eat y
如果x和y(或x和y+2*n)同属一棵树,那么代表x和y有同级(被吃)的关系,矛盾
连(x,y+n) (x+n,y+2*n) (x+2*n,y)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <ctime> 5 #include <cstring> 6 #include <string> 7 #include <map> 8 #include <set> 9 #include <list> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <bitset> 14 #include <algorithm> 15 #include <iostream> 16 using namespace std; 17 #define ll long long 18 const int maxn=5e4+10; 19 20 int fa[maxn*3]; 21 22 int getf(int d) 23 { 24 if (fa[d]==d) 25 return d; 26 fa[d]=getf(fa[d]); 27 return fa[d]; 28 } 29 30 void _union(int x,int y) 31 { 32 int xx=getf(x); 33 int yy=getf(y); 34 fa[xx]=yy; 35 } 36 37 int main() 38 { 39 int n,t,mode,x,y,x1,y1,y2,lie=0,i; 40 scanf("%d%d",&n,&t); 41 for (i=1;i<=3*n;i++) 42 fa[i]=i; 43 ///x eat y k -> (k+n) mod (3*n) 44 ///judge:use any(both ok) ; handle:all 45 while (t--) 46 { 47 scanf("%d%d%d",&mode,&x,&y); 48 if (x>n || y>n) 49 { 50 lie++; 51 continue; 52 } 53 if (mode==1) 54 { 55 ///x,y same 56 x1=getf(x); 57 y1=getf(y+n); 58 y2=getf(y+n+n); 59 if (x1==y1 || x1==y2) 60 lie++; 61 else 62 { 63 _union(x,y); 64 _union(x+n,y+n); 65 _union(x+n+n,y+n+n); 66 } 67 } 68 else 69 { 70 ///x eat y 71 x1=getf(x); 72 y1=getf(y); 73 y2=getf(y+n+n); 74 if (x1==y1 || x1==y2) 75 lie++; 76 else 77 { 78 _union(x,y+n); 79 _union(x+n,y+n+n); 80 _union(x+n+n,y); 81 } 82 } 83 } 84 printf("%d",lie); 85 return 0; 86 }