You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

##AcWing 837. 连通块中点的数量

一、题目描述

给定一个包含 n 个点(编号为 1n)的无向图,初始时图中没有边。

现在要进行 m 个操作,操作共有三种:

  • C a b,在点 a 和点 b 之间连一条边,ab 可能相等;
  • Q1 a b,询问点 a 和点 b 是否在同一个连通块中,ab 可能相等;
  • Q2 a,询问点 a 所在连通块中点的数量;

输入格式 第一行输入整数 nm

接下来 m 行,每行包含一个操作指令,指令为 C a bQ1 a bQ2 a 中的一种。

输出格式 对于每个询问指令 Q1 a b,如果 ab 在同一个连通块中,则输出 Yes,否则输出 No

对于每个询问指令 Q2 a,输出一个整数表示点 a 所在连通块中点的数量

每个结果占一行。

数据范围 1≤n,m≤10^5

输入样例:

5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5

输出样例:

Yes
2
3

二、题目解析

并查集 + 附加信息,附加信息为家族中成员的数量,需要一个额外的数组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() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) p[i] = i, s[i] = 1;

    while (m--) {
        string op;
        int a, b;
        cin >> op;
        if (op == "C") {
            cin >> a >> b;
            if (find(a) != find(b)) {
                s[find(b)] += s[find(a)];
                p[find(a)] = find(b);
            }
        } else if (op == "Q1") {
            cin >> a >> b;
            if (find(a) == find(b))
                puts("Yes");
            else
                puts("No");
        } else {
            cin >> a;
            printf("%d\n", s[find(a)]);
        }
    }
    return 0;
}