拆点;一个点i可能的种类为A,B,C
将一个点i拆成三个点,相当于三种情况;
i表示A,i+n表示B,i+n+n表示C
#include<bits/stdc++.h> using namespace std; #define int long long int fa[151000],k,n; int find(int x) { return fa[x]==x ? x:fa[x]=find(fa[x]); } int merge(int a,int b) { fa[find(a)]=find(b); return 0; } signed main() { cin>>n>>k; int cnt=0; for(int i=1;i<=3*n;i++) fa[i]=i; for(int i=1;i<=k;i++) { int d,x,y; cin>>d>>x>>y; if(x>n||y>n) {cnt++;continue;} if(d==1) { if(find(x)==find(y+n)||find(x)==find(y+2*n)){ cnt++;continue; } merge(x,y);//如果x与y同类,x的每个情况都与y的每个情况在同一个集合; merge(x+n,y+n); merge(x+n+n,y+n+n); } else{ if(find(x)==find(y)||find(x)==find(y+2*n)){ cnt++;continue; } merge(x,y+n);//x吃y,则可能的情况AB、BC、CA; merge(x+n,y+2*n); merge(x+2*n,y); } } cout<<cnt; return 0; }