并查集。看了《挑战程序设计竞赛》才会的。POJ多组数据提交会WA。
主要思路是把一个点拆成三个点。i,i+n,i+2*n分别表示 i 是A类,B类,C类。
如果 i 和 j+n在同一集合内,表示 i 是A类的时候,j 一定是B类。
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int maxn=50000+10; int n,k,ans; int f[3*maxn]; int Find(int x) { if(x!=f[x]) f[x]=Find(f[x]); return f[x]; } void init() { ans=0; for(int i=1;i<=3*n;i++) f[i]=i; } void u(int a,int b) { int fa=Find(a),fb=Find(b); if(fa!=fb) f[fa]=fb; } bool p(int a,int b) { int fa=Find(a),fb=Find(b); if(fa==fb) return 1; return 0; } void work() { 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(p(x,y+n)||p(x,y+2*n)) {ans++;continue;} u(x,y); u(x+n,y+n); u(x+2*n,y+2*n); } else if(d==2) { if(p(x,y)||p(y+2*n,x)) {ans++;continue;} u(x,y+n); u(x+n,y+2*n); u(x+2*n,y); } } printf("%d ",ans); } int main() { scanf("%d%d",&n,&k); init(); work(); return 0; }