截止目前见过的最难的并查集,对于每个动物建立3个元素i-A,i-B,i-C,其中i-X代表i属于x类,并查集内部的每一个组代表的都是这个组中的情况全都发生或者不发生。
例如:如果i-A和j-B在同一个组内,就表示i如果属于A那么j一定属于B,反过来也是。因此对于每一条信息,只需要按照下面的情况进行操作就行了。
1:x和y属于同一类合并x-A,y-A和x-B,y-B,和x-C,y-C
2:第二种,合并x-A,y-B,和x-B,y-C和x-C,y-A。
在合并之前判断是否矛盾就可以了。
#include<stdio.h> int p[150010]; int find(int x) { return p[x]==x ? x : p[x]=find(p[x]); } bool same(int x,int y) { return find(x)==find(y); } void unite(int x,int y) { int u = find(x); int v = find(y); if(u != v) p[u] = v; } int main() { int N, K, D, x, y, ans = 0; scanf("%d%d", &N,&K); for(int i=1; i<3*N; i++) p[i] = i; while(K--) { scanf("%d%d%d", &D,&x,&y); if(x>N || y>N) { ans++; continue; } if(D == 1) { if(same(x,y+N) || same(x,y+2*N)) ans++; else { unite(x,y); unite(x+N,y+N); unite(x+2*N,y+2*N); } } else { if(same(x,y) || same(x,y+2*N)) ans++; else { unite(x,y+N); unite(x+N,y+2*N); unite(x+2*N,y); } } } printf("%d\n", ans); return 0; }