并查集
首先先要读懂题目,a是b的食物的话,b的天敌是a,b的食物是a的天敌
比如,人吃鸡,鸡吃草,那么草吃人。。。。。
所以建3个并查集,+n时表示这是其食物,+2*n时表示这是其天敌
所以当x,y是同类当且仅当x的食物不是y,且x的天敌不是y
当x吃y当且仅当x和y不是同类,y的食物不是x
然后并查集维护即可
#include <bits/stdc++.h> using namespace std; const int MAXN=51000; int n,k,fa[MAXN*4],ans;//1 same 2 food 3 enemy inline int find(int x) { if (fa[x]==x) return fa[x]; fa[x]=find(fa[x]); return fa[x]; } void unite(int x,int y) { int fx,fy; fx=find(x); fy=find(y); fa[fx]=fy; } int main() { scanf("%d%d",&n,&k); for (int i=1;i<=3*n+10;i++) fa[i]=i; for (int i=1;i<=k;i++) { int d,x,y; scanf("%d%d%d",&d,&x,&y); if (x>n ||y>n) { ans++; continue; } if (d==1) { if (find(x+n)==find(y) || find(x+n*2)==find(y)) { ans++; continue; } unite(x,y); unite(x+n,y+n); unite(x+2*n,y+2*n);//三个并查集的同类都要连起来 } else { if (x==y || find(x)==find(y) || find(x+2*n)==find(y)) { ans++; continue; } unite(x+n,y); unite(x+2*n,y+n); unite(x,y+2*n);//三个并查集维护 } } printf("%d\n",ans); }