题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1182 题意简述:中文题目就不敷述。 解题思路:代码有注释。 代码: #include <iostream> #include <cstdio> using namespace std; const int MAXN = 50001; struct Node { int parent; int rank; }food[MAXN]; void makeset(int n) { //初始化并查集 for(int i = 1; i <= n; i++) { food[i].parent = i; //每个元素单独作为一个集合 food[i].rank = 0; //i元素相对集合的根元素的类型差值, //由于刚开始时集合的根也是i属于同种类型,故相对差值为0 } } int find(int x) { int t = food[x].parent; if(t != x) { food[x].parent = find(t); //更驰元素相对集合根元素的差值, //food[x].rank是x元素相对原来的根元素t的差值,现在的根元素已不是t, //故要加上t对于现在的根元素的类型差值,food[t].rank为t对于现在根元素类型的差值 food[x].rank = (food[x].rank + food[t].rank) % 3; } return food[x].parent; } int main() { int n, k, lie = 0; scanf("%d %d", &n, &k); makeset(n); while(k --) { int x, y, d; scanf("%d %d %d", &d, &x, &y); if(x > n || y > n) lie ++; //当前的话中X或Y比N大,就是假话 else if(d == 1) { //表示X和Y是同类 int a = find(x); //寻找元素x所在集合的根元素 int b = find(y); //寻找元素y所在集合的根元素 if(a == b) { //x y为在同一集合时,表明之前已经之前已经做了并操作 //现在输入的d = 1表明x y为同类, //则它们相对根元素的类型差值也就该相同,否则就是谎言 if(food[x].rank != food[y].rank) lie ++; }else { food[a].parent = b; //集合a和b相并成一个集合,集合的根元素为b,则此时要修改a到b的类型差值 //由于d = 1表明x,y同类型,则修改后的food[y].rank = food[x].rank(注意此时尚未修改), //现在的food[x].rank仍为x相对于a的类型差, //这里先用(food[y].rank - food[x].rank + 3) % 3 作为修改后的food[a].rank //等到有执行到find操作时才更新food[x].rank,那时修改后的food[x].rank = (food[x].rank + food[a].rank) % 3 //修改后的food[x].rank == food[y].rank (满足现在d = 1时 x y同类型的情况) food[a].rank = (food[y].rank - food[x].rank + 3) % 3; } }else if(d == 2) { if(x == y) lie ++; else { int a = find(x); int b = find(y); if(a == b) { if(food[x].rank != (food[y].rank + 1) % 3) lie ++; }else { food[a].parent = b; food[a].rank = (food[y].rank - food[x].rank + 4) % 3; } } } } printf("%d/n", lie); system("pause"); return(0); }