并查集
题目
对于每一对点,只要他们是有关系的,无论是关系1, 还是2,都放到一个树里面。
这道题主要就是要知道每一个点和根节点之间的关系,如果节点和根节点的高度差模3为1, 说明该节点可以吃根节点,如果为2,那说明,根节点可以吃该节点,如果为0,那么说明,该节点和根节点是同类。
这个距离是怎么确定的呢?主要通过吃的关系来确定。设根为第0代,吃根的就是第一代,吃第二代的就是第三代,以此类推。
本题就是用并查集来维护某一点到根节点的距离。我们知道的是某一点和其父节点的距离,其和根节点的距离还需要进一步求
代码如下:`
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 50010;
int p[N], d[N]; //d记录的是某一点和其父节点的距离,因为初始时父节点就是节点自身,所以初始值为0
int find(int x){
if(x != p[x]){
int u = find(p[x]);
d[x] += d[p[x]];
p[x] = u;
}
return p[x];
}
int main(){
int n, k;
cin >> n >> k;
int res = 0;
for(int i = 1; i <= n ;i++) p[i] = i;
while(k--){
int a, b, c;
cin >> a >> b >> c;
if(b > n || c > n) res++;
else {
int px = find(b), py = find(c);
if(a == 1){
if(px == py && (d[b] - d[c]) % 3) res++;//当b, c为同类,那么他们的差值肯定是整除3
else if(px != py){
p[px] = py;
d[px] = d[c] - d[b];
}
}
else{
//属于一个集合,但是b吃不了c
if(px == py && (d[b] - d[c] - 1) % 3) res ++;
else if(px != py){
//不属于同一个集合,更新d
p[px] = py;
d[px] = d[c] - d[b] + 1;
}
}
}
}
printf("%d\n", res);
return 0;
}