AcWing 836. 合并集合(并查集基础)
原题链接
简单
作者:
飞吧
,
2020-07-19 18:16:11
,
所有人可见
,
阅读 1141
并查集解决的问题:
- 合并两个集合
- 查询两个元素是否属于同一个集合
基本思路:
- 每个集合用树表示,树根元素的编号作为树的编号
- 用p[]数组记录父节点所属集合的编号
Task:
- 如何判断树根: if(p[x] == x)
- 如何求元素的集合编号: while(p[x] != x) x = p[x];
- 如何合并集合x和集合y: p[x] = y;
优化:
- 路径压缩:这样只需要查询一次O(logn),后续的所有查询都变为O(1)了
- 加权合并(节点少的合并向节点多的):优化的很少
题解:
#include<iostream>
using namespace std;
const int N = 100010;
int n, m;
int p[N];
int find(int x)
{
if(x != p[x]) p[x] = find(p[x]);
return p[x]; //查询父节点的同时进行路径压缩
}
int main()
{
cin >> n >> m;
//初始化
for(int i = 1; i <= n; i++) p[i] = i;
while(m--){
char op;
int a, b;
cin >> op >> a >> b;
if(op == 'M')
p[find(a)] = find(b); //这里特别容易错写成p[a] = b。注意合并必须合并祖先!
else{
if(find(a) == find(b)) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
}