并查集维护某一个关系,食物链

并查集

题目
在这里插入图片描述
对于每一对点,只要他们是有关系的,无论是关系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;    
}

猜你喜欢

转载自blog.csdn.net/qq_44879626/article/details/108046335