[NOI2001]食物链
传送门
Solution
因为只有3种关系,可以用种类并查集。
考虑维护3个东西\(A\),\(B\),\(C\),分别表示\(A\)这种生物,\(A\)能够吃的生物\(B\)的集合,能够吃\(A\)的集合\(C\),然后并查集分别维护即可。
Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<set> #include<map> #include<iostream> using namespace std; #define ll long long #define REP(a,b,c) for(int a=b;a<=c;a++) #define re register #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) inline int gi(){ int f=1,sum=0;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return f*sum; } const int N=500010; int f[N],n,k,ans; int find(int x){return f[x]==x?f[x]:f[x]=find(f[x]);} int main(){ n=gi();k=gi();for(int i=1;i<=n*3;i++)f[i]=i; while(k--){ int opt=gi(),x=gi(),y=gi();if(x>n || y>n){ans++;continue;} if(opt==1){ if(find(x)==find(y+n) || find(x+n)==find(y)){ans++;continue;} f[find(y)]=find(x); f[find(y+n)]=find(x+n); f[find(y+2*n)]=find(x+2*n); } else{ if(find(x)==find(y) || find(x)==find(y+n)){ans++;continue;} f[find(x+n)]=find(y); f[find(x+2*n)]=find(y+n); f[find(x)]=find(y+2*n); } } printf("%d\n",ans); return 0; }