AcWing 837. 连通块中点的数量

题目传送门

一、理解与感悟

并查集+附加信息,附加信息为家族中成员的数量,需要一个额外的数组(s[N])记录以结点(i)为根的的家族成员数量。

与最祼并查集的区别:

  • 初始化时需要将(s[i]=1)

  • 合并时,需要(s[find(b)]+ =s[find(a)])

  • 查询时:(s[find(a)])

二、实现代码

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

int n, m;
int p[N];     //爸爸数组
int s[N];    //每一个集合中点的数量

//递归查找父节点
int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main() {
    //优化输入
    ios::sync_with_stdio(false);
    cin >> n >> m;

    //并查集初始化
    for (int i = 1; i <= n; i++) {
        p[i] = i;
        s[i] = 1; //每个家族的成员数:1
    }

    while (m--) {
        string op;
        int a, b;
        cin >> op;
        if (op[0] == 'C') {
            cin >> a >> b;
            //如果a和b已经在同一个集合里了,那么就不需要进行处理了
            if (find(a) == find(b)) continue;
            //如果a和b不在同一个集合中
            s[find(b)] += s[find(a)];//更新族长记录的家族人员数量
            p[find(a)] = find(b);    //实现两个集合的合并
        } else if (op[1] == '1') {
            cin >> a >> b;
            if (find(a) == find(b)) puts("Yes"); // 两个节点在一个集合里
            else puts("No");    //不在一个集合里
        } else {
            //查询个数
            cin >> a;
            printf("%d
", s[find(a)]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/littlehb/p/15268351.html