/** * 种类并查集: * 这题数据天坑呐。。 必须单组才能AC,用多组数据输入就WA。 * 就下程序而言: Node中的fa表示他爸,re表示他和他爸的关系(吃他爸:1,被他爸吃:2,还是同类:0)。 * 当该节点没爸的时候,也就是本身就是根节点的时候,re就是0(和自己同类),他所有儿子的re都是和他的关系。 * 这题难点主要就是找规律且要在合并两个集合的时候怎么改变关系re; * 我的思路是,把a对b的关系用向量来表示,如:a->b 如果re是1 就是a吃b, 2就是a被b吃, 0同类 * 这样当a->b, b->c的时候可以找到 a->c的关系:num[pre].re = (num[fa].re + num[pre].re) % 3 * 有了这个关系在合并集合的时候就可以用了。 有的时候还要转换,就是比如: * 根据之前的规律可以求出a->c, 可是我需要的是c->a 其实,就可以一一考虑情况 * 当a->c 的re = 1的时候,改2,2的时候改1,0的时候不变。。这样就转换为c->a的关系了 * 具体的合并过程: 什么时候要合并? * 当给两个节点x, y的时候find(x) != find(y) 也就是不同爸,说明该话是真,但是需要合并。 * 函数Union(int d, int x, int y) 中 d为y->x的关系re * Union就是把x所处集合作为y的儿子来合并集合的。 * 这个时候已知的有: y->x x->find(x), 就可以求 y->find(x) 再求 find(x)->y 最后把这个re给num[find(x)].re * 当然还有很多细节,比如题目给的d只有1,2要把1转为0,还有父亲的变化,也就是并查集的维护等等。 */ #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <algorithm> #define INF 0x7fffffff #define MAXS 50001 #define LL long long using namespace std; int n, k; struct Node{ int fa, re; } num[MAXS]; void init() { for(int i = 1; i <= n; i ++) { num[i].fa = i; num[i].re = 0; } } int find(int pre) { int fa = num[pre].fa; if(num[fa].fa == fa) { return num[pre].fa; } else { num[pre].fa = find(num[pre].fa); num[pre].re = (num[fa].re + num[pre].re) % 3; return num[pre].fa; } } void Union(int x, int y, int d) { int td, xfa; xfa = find(x); num[xfa].fa = y; td = (num[x].re + d) % 3; if(td == 1) num[xfa].re = 2; else if(td == 2) num[xfa].re = 1; else num[xfa].re = 0; } bool judge(int d, int x, int y) { if(x > n || y > n) return false; if(d == 2 && x == y) return false; if(d == 0) { if(find(x) == find(y)) { if(num[x].re != num[y].re) return false; else return true; } else { Union(x, y, d); return true; } } else if(d == 2) { if(find(x) == find(y)) { if(num[x].re == 0 && num[y].re == 2 || num[x].re == 1 && num[y].re == 0 || num[x].re == 2 && num[y].re == 1) return true; else return false; } else { Union(x, y, d); return true; } } } int main() { scanf("%d%d", &n, &k); int X, Y, d, cnt = 0; init(); for(int i = 0; i < k; i ++) { scanf("%d%d%d", &d, &X, &Y); if(d == 1) d = 0; if(!judge(d, X, Y)) cnt ++; } printf("%d\n", cnt); return 0; }