透过一张图 彻底明白并查集维护与祖宗结点关系的方法

算法详解

在这里插入图片描述

238.银河英雄传说(维护与祖宗结点的距离)

在这里插入图片描述

/**
 *    @Author: Wilson79
 *    @Datetime: 2019年12月22日 星期日 11:43:37
 *    @Filename: 238.银河英雄传说.cpp
 */

// 用size去维护每个连通块的个数,d[x]表示x到当前祖宗结点的距离,d[x]在find一次后会更新
// 每次把size加到pa上,这样整个pa连通块上的点的d[i],之后更新时都会加上这个size
    
#include <iostream>

using namespace std;

const int N = 30010;

int p[N], d[N], size[N];
int a, b;

int find(int x) {
    if (p[x] != x) {
        int root = find(p[x]); // 递归到底
        d[x] += d[p[x]]; // 从底往回,更新距离
        p[x] = root; // 压缩路径
    }
    return p[x];
}


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

    for (int i = 0; i < N; i ++) {
        p[i] = i;
        size[i] = 1;
        d[i] = 0;
    }

    while(T --) {
        char op[2]; // 用scanf读单个字符的巧妙写法
        scanf("%s%d%d", op, &a, &b);

        if (op[0] == 'M') {
            int pa = find(a), pb = find(b);
            d[pa] += size[pb]; // 把size加到pa结点即可,这样原pa连通块上的距离在之后find时都会加上这个size
            size[pb] += size[pa];
            p[pa] = pb;
        } else {
            int pa = find(a), pb = find(b);
            // 必须find一次,才能把d[a],d[b]更新到最新
            if (pa != pb) cout << "-1" << endl;
            else {
                cout << max(abs(d[a] - d[b]) - 1, 0) << endl;
            }
        }
    }


    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

捡起一束光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值