关键思路:扩展域并查集:
前提主观表明:fa[N]: x,x+n为食物,x+n+n为天敌
0-n存储个体,n+1到2n存储食物,2n+1到3n存储天敌
图例:
ACcode:
扩展域并查集
x,x+n代表x的敌人,x+n+n代表x的天敌
#include<iostream>
using namespace std;
const int N=3*(5e4+10);
int fa[N];
int n,k,ans;
void init() {//初始化父节点
for(int i=1; i<=3*n; i++) {
fa[i]=i;
}
return;
}
int find(int x) {//查找父节点
return fa[x]==x?x:fa[x]=find(fa[x]);
}
//x,x+n==食物,x+n+n==天敌
int main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);//输入"加速"
cin>>n>>k;
init();
for(int i=1; i<=k; i++) {
int op,x,y;
cin>>op>>x>>y;
if(x>n||y>n) {//假话1
ans++;
continue;
}
if(op==1){
if(find(x+n)==find(y)||find(x+n+n)==find(y)){//不符合之前的推理,假话
ans++;
continue;
}
else{//合法 ,同类归并(同类每总都并)
fa[find(x)]=fa[find(y)];//x,y是同类
fa[find(x+n)]= fa[(find(y+n))];//那么他们的食物相同
fa[find(x+n+n)]=fa[find(y+n+n)];//那么他们的天敌相同
}
}
else{//x吃y ,不合理(题意是x吃y)假话
if(find(x+n+n)==find(y)||find(x)==find(y)){
ans++;
continue;
}
else{//合法
fa[find(x+n)]=fa[find(y)];//y是x的食物
fa[find(x+n+n)]=fa[find(y+n)];//y的食物是x的天敌
fa[find(y+n+n)]=fa[find(x)];//循环回来y的天敌是x,很合理操作
}
}
}
cout<<ans;//结果
return 0;
}