题目地址:
https://www.acwing.com/problem/content/838/
一共有
n
n
n个数,编号
1
∼
n
1\sim n
1∼n,最开始每个数各自在一个集合中。现在进行
m
m
m次操作,每次:
(1)M a b
,将编号为
a
a
a和
b
b
b的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;
(2)Q a b
,询问编号为
a
a
a和
b
b
b的两个数是否在同一个集合中;
输入格式:
第一行输入整数
n
n
n和
m
m
m。接下来
m
m
m行,每行包含一个操作指令,指令为M a b
或Q a b
中的一种。
输出格式:
对于每个询问指令Q a b
,都要输出一个结果,如果
a
a
a和
b
b
b在同一集合内,则输出Yes
,否则输出No
。每个结果占一行。
数据范围:
1
≤
n
,
m
≤
1
0
5
1\le n,m\le 10^5
1≤n,m≤105
可以用并查集。代码如下:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int p[N];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) p[i] = i;
while (m--) {
char op;
int a, b;
cin >> op;
cin >> a >> b;
int pa = find(a), pb = find(b);
if (op == 'M') p[pa] = pb;
else if (op == 'Q') pa == pb ? puts("Yes") : puts("No");
}
}
每次操作时间复杂度 O ( log ∗ n ) O(\log ^*n) O(log∗n),空间是 O ( n ) O(n) O(n)。