并查集
概念讲解
什么是并查集?
并查集是一种处理不相交集合的合并与查询问题的数据结构。
基本操作
| 操作 | 说明 |
|---|---|
| Find | 查找元素所属集合 |
| Union | 合并两个集合 |
基础实现
路径压缩
123456789101112131415const int N = 100005;
int parent[N];
void init(int n) {
for (int i = 1; i <= n; i++) parent[i] = i;
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
void unite(int x, int y) {
parent[find(x)] = find(y);
}按秩合并
123456789int rank[N];
void unite(int x, int y) {
int rx = find(x), ry = find(y);
if (rx == ry) return;
if (rank[rx] < rank[ry]) swap(rx, ry);
parent[ry] = rx;
if (rank[rx] == rank[ry]) rank[rx]++;
}时间复杂度
| 操作 | 时间复杂度 |
|---|---|
| find | O(α(n)) ≈ O(1) |
| unite | O(α(n)) ≈ O(1) |
α 是反阿克曼函数,几乎为常数。
应用
- 判断连通性
- 最小生成树(Kruskal)
- 集合合并
考点分析
初赛考查方式
- 程序阅读: 并查集操作
- 编程题: 连通性问题
常见考点
- 路径压缩
- 按秩合并
- 连通块计数
例题精讲
例题 1:连通块
题目: 判断两个点是否连通。
解答:
123if (find(x) == find(y)) {
cout << "连通" << endl;
}练习题
- 路径压缩的作用是什么?
查看答案
路径压缩的作用是降低树的高度,使 find 操作更快。
1234int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}路径压缩后,树的高度几乎为 2,find 操作接近 O(1)。
- 按秩合并的作用是什么?
查看答案
按秩合并的作用是保持树的平衡,避免退化成链。
1234567void unite(int x, int y) {
int rx = find(x), ry = find(y);
if (rx == ry) return;
if (rank[rx] < rank[ry]) swap(rx, ry);
parent[ry] = rx;
if (rank[rx] == rank[ry]) rank[rx]++;
}总是将小树合并到大树上。
- 并查集的时间复杂度是多少?
查看答案
并查集的时间复杂度:
- find:
- unite:
其中 是反阿克曼函数,几乎为常数。
易错点
⚠️ 注意:
- 初始化时 parent[i] = i
- find 要路径压缩
- unite 前要判断是否已连通
- 按秩合并可以进一步优化