0
点赞
收藏
分享

微信扫一扫

Acwing 240食物链

RJ_Hwang 2022-04-13 阅读 51

本题解题方法是并查集维护额外信息解决问题

记录每个节点到父结点的距离d[i],会有以下三种情况

d[i]%3=0, p[i]与i是统一种动物

d[i]%3=1 i吃p[i]

d[i]%3=2 p[i]吃i

在代码之前解释一下这个并查集find函数吧

如果一个节点的父节点就是整个集合的根节点,则find递归回溯过程中d[x]+=0;

所以对于所有路径已经压缩过的节点,他们的d[x]在进行find操作时时不会受到影响,也就是说此时的find函数和普通并查集函数的效果相同。

而如果该节点的父节点不是整个集合的根节点,比如如下情况,讲x这个集合合并到y上会出现以下情况。

对于这种情况,并查集会一直这样保存,直到下一次对x进行查询,也就是对x进行find操作,此时我们会将并查集更新成如下情形,并且d[x]的值更新为x到py的距离。

 

 

 直接上y总的代码吧

 

#include <iostream>

using namespace std;

const int N = 50010;

int n, m;
int p[N], d[N];

int find(int x)
{
    if (p[x] != x)
    {
        int t = find(p[x]);
        d[x] += d[p[x]];
        p[x] = t;
    }
    return p[x];
}

int main()
{
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= n; i ++ ) p[i] = i;

    int res = 0;
    while (m -- )
    {
        int t, x, y;
        scanf("%d%d%d", &t, &x, &y);

        if (x > n || y > n) res ++ ;
        else
        {
            int px = find(x), py = find(y);
            if (t == 1)
            {
                if (px == py && (d[x] - d[y]) % 3) res ++ ;
                else if (px != py)
                {
                    p[px] = py;
                    d[px] = d[y] - d[x];
                }
            }
            else
            {
                if (px == py && (d[x] - d[y] - 1) % 3) res ++ ;
                else if (px != py)
                {
                    p[px] = py;
                    d[px] = d[y] + 1 - d[x];
                }
            }
        }
    }

    printf("%d\n", res);

    return 0;
}

/*作者:yxc
链接:https://www.acwing.com/activity/content/code/content/45325/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/

·

举报

相关推荐

0 条评论