正文
第二题:食物链
这题经典啊!!!我们可以想象,如果我们可以搞一个并查集来维护x的同伙,天敌和食物就好了。
我们想到了开三倍空间来维护x的天敌,同伙和食物。
我们假设有一句话是x和y是同类,那么要满足两个条件,x不吃y,而且y不吃x。如果都满足,那么我们就可以把他们联系起来。
我们再假设一句话是x吃y,那么要满足的条件显然有,x和y不为同类,而且y不吃x。
我们再把他们联系起来即可。
怎么联系呢?,我们看代码吧~
#include<cstdio>
#include<cstdlib>
#include<cstring>
int n,m;
int f[150010];//1<=i<=50000 1到50000表示i的同类,i+n表示i的食物,i+2*n为i的天敌。
int ans=0;
int findpa(int x){
if(f[x]!=x) return f[x]=findpa(f[x]);
return f[x];
}
bool comp(int x,int y){
return findpa(x)==findpa(y);
}
void couple(int x,int y){
if(findpa(x) != findpa(y)) f[findpa(x)]=findpa(y);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=3*n;i++)
f[i]=i;
for(int i=1;i<=m;i++){
int k,x,y;
scanf("%d %d %d",&k,&x,&y);
if(k==2 && x==y || x>n || y>n){
ans++;
continue;
}
if(k==1){
if(comp(x,y+n) || comp(x+n,y)){//x不吃y,而且y不吃x。
ans++;
continue;
}
couple(x,y);
couple(x+n,y+n);
couple(x+2*n,y+2*n);
}
else{
if(comp(x,y+n) || comp(x,y)){//x和y不为同类,而且y不吃x
ans++;
continue;
}
couple(x,y+2*n);
couple(x+n,y);
couple(x+2*n,y+n);
}
}
printf("%d\n",ans);
}