并查集学习笔记
vegetaBle_king · · 个人记录
前置知识:树的父亲表示法。
并查集基础
并查集,又称 DSU,是一个可以动态维护若干个不重叠的集合的数据结构。
并查集支持的基本操作有两种:
- 查询一个元素在哪一个集合里。
- 合并两个集合。
并查集的思想是将每一个集合存储为一棵有根树,以树根为这棵树的代表。我们可以记录一个
优化
但是,这棵有根树可能退化成链,单次查询的时间复杂度就会退化成
路径压缩
我们可以使用“路径压缩”的思想,在查询一个节点
按秩合并
还有一种优化方法,就是“按秩合并”。在每一个节点上多维护一个
同时使用路径压缩优化和按秩合并优化的并查集,每一次查询的均摊时间复杂度可看作一个常数忽略不计,与
一般在使用并查集时,我们只需要使用路径压缩优化就够了。
模板题代码:
#include <iostream>
using namespace std;
int n, m, p, f[10001], u, v;
int getfa(int x){
if (f[x] == x) return x;
return f[x] = getfa(f[x]);
}
void merge(int a, int b){
f[getfa(a)] = getfa(b);
}
bool check(int a, int b){
return getfa(a) == getfa(b);
}
int main(){
cin >> n >> m;
for (int i = 1;i <= n;i ++) f[i] = i;
for (int i = 1;i <= m;i ++){
cin >> p >> u >> v;
if (p == 1) merge(u, v);
else {
if (check(u, v)) cout << "Y\n";
else cout << "N\n";
}
}
}
“扩展域”与“边带权”的并查集
有时候,一般的并查集无法维护题目中各种各样的传递关系,我们就可以使用“扩展域”与“边带权”的并查集。
拓展域
“拓展域”,顾名思义就是把一个节点拆成多个节点,记录所有情况,合并时将所有情况都合并。
边带权
“边带权”,顾名思义也就是将维护的无权树变为有权树,边的权可以记录一些信息。而路径压缩后,
例题
【模板】并查集
[NOI2015] 程序自动分析
Supermarket
[NOI2002] 银河英雄传说
[CEOI1999] Parity Game
[NOI2001] 食物链
[NOIP2010 提高组] 关押罪犯
石头剪子布