其他分享
首页 > 其他分享> > [AcWing 240] && P2024 [NOI2001] 食物链

[AcWing 240] && P2024 [NOI2001] 食物链

作者:互联网

image
image


点击查看代码
#include<iostream>

using namespace std;
const int N = 5e5 + 10;
int p[N], d[N];
int find(int x)
{
    if (p[x] != 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;
    for (int i = 1; i <= n; i ++)   p[i] = i;
    int res = 0;
    while (k --) {
        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];
                }
            }
        }
    }
    cout << res;
    return 0;
}

  1. 维护一个并查集的同时,记录每个节点到根节点的距离,距离为 1 表示可以吃根节点,距离为 2 表示可以被根节点吃,距离为 3 表示和根节点是同类;
  2. 距离的更新在 find 中完成,u = find( p[ x ] ) 有两个作用,一个是记录根节点,一个是更新 p[ x ] 后面节点到根节点的距离,执行完这条语句后,d[ p[ x ] ] 就是 p[ x ] 到根节点的距离;
  3. res ++ 有 3 种情况:
    ① x > n 或者 y > n,违背了条件 2;
    ② t == 1,x 和 y 同属于一个集合,但是 d[ x ] % 3 和 d[ y ] % 3 的值不同,也就是 (d[ x ] - d[ y ]) % 3 != 0,那么根据距离的意义,x 和 y 与根节点的关系必不相同,从而推出 x 和 y 必不是同类,与 t == 1 表示 x 和 y 是同类矛盾,违背了条件 1;
    ③ t == 0,x 和 y 属于同一个集合,若要 x 吃 y,根据题目条件,只有 a 吃 b,b 吃 c 时,可以推出 c 吃 a,那么要想让 x 吃 y,则要让 y 吃根节点,根节点吃 x,那么就可以推出 x 吃 y,在这种条件下,d[ x ] 和 d[ y ] 需要满足一定的条件,y 吃根节点,说明 d[ y ] % 3 == 1,x 被根节点吃,说明 d[ x ] % 3 == 2,也就是 (d[ x ] - d[ y ] - 1) % 3 == 0,那么如果 (d[ x ] - d[ y ] - 1) % 3 != 0,就肯定没有 x 吃 y,与 t == 0 表示 x 吃 y 矛盾,违背了条件 1;(x 吃 x 可以看作是 x 吃 y,当 y = x 时的特例,同时也违背了条件 3)
  4. 需要合并并查集的 2 种情况:
    ① t == 1,x 和 y 不属于同一个集合,让 x 的根节点作为 y 的根节点的孩子节点,需要让 d[ px ] 取一定的值,满足 t == 1 时,x 和 y 同类这个条件,此时,x 到 y 的根节点的距离为 d[ x ] + d[ px ],y 到 y 的根节点的距离为 d[ y ],两个距离 % 3 的值应该相同,取一种简单的情况,两个距离相等,由 d[ x ] + d[ px ] = d[ y ] 可以推出 d[ px ] = d[ y ] - d[ x ];
    ② t == 0,x 和 y 不属于同一个集合,让 x 的根节点作为 y 的根节点的孩子节点,需要让 d[ px ] 取一定的值,满足 t == 0 时,x 吃 y 这个条件,此时,x 到 y 的根节点的距离为 d[ x ] + d[ px ],y 到 y 的根节点的距离为 d[ y ],x 的这个距离应当 % 3 = 2,y 的这个距离应当 % 3 = 1,取一种简单的情况,让两个距离的差值为 1,由 d[ x ] + d[ px ] - d[ y ] = 1 可以推出 d[ px ] = d[ y ] + 1 - d[ x ];

标签:P2024,int,px,py,距离,find,240,&&,节点
来源: https://www.cnblogs.com/wKingYu/p/16217439.html