luogu2024 食物链 (并查集)
把一个点拆成三个,分别对应它的同类、它的猎物和它的天敌,这样的话(以下的相等都是并查集意义上的):
如果令a,b同类,那么a的猎物不能是b的同类,a的天敌不能是b的同类
如果令a吃b,那么a的同类不能是b的同类、a的天敌不能是b的同类。
要令a,b同类,就使(a和b)的同类、猎物、天敌分别相等
要令a吃b,就使a的猎物是b的同类,b的天敌是a的同类,a的天敌是b的猎物(题目中要求A吃B,B吃C,C吃A)
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=50050; 6 7 inline ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x*neg; 12 } 13 14 int N,K,fa[maxn*3]; 15 16 int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);} 17 void add(int a,int b){ 18 fa[getfa(a)]=getfa(b); 19 } 20 21 int main(){ 22 //freopen("testdata.in","r",stdin); 23 int i,j,k,ans=0; 24 N=rd();K=rd(); 25 for(i=1;i<=N*3;i++) fa[i]=i; 26 for(i=1;i<=K;i++){ 27 int a=rd(),b=rd(),c=rd(); 28 if(b>N||c>N) {++ans;continue;} 29 if(a==1){ 30 if(getfa(b)==getfa(c+N)||getfa(b)==getfa(c+2*N)){++ans;continue;} 31 add(b,c);add(b+N,c+N);add(b+2*N,c+2*N); 32 }else{ 33 if(getfa(b)==getfa(c)||getfa(b+2*N)==getfa(c)){++ans;continue;} 34 add(b+N,c);add(b,c+2*N);add(b+2*N,c+N); 35 } 36 } 37 printf("%d\n",ans); 38 return 0; 39 }