并查集(Union Find Set)
1 基本介绍
并查集是一种用来判断两个元素之间是否有关系的集合。
它的基本思想为:对于两个元素,如果他们之间有关系,则将其连接,以此形成一颗树。
对于任意两个节点,如果它们有相同的根节点,则它们之间有关系。
2. 建立步骤
给定n个点,以及m个关系。
1. 初始状态
将每个节点的根节点都指向自己
for (int i = 0; i < n; i++) { pre[i] = i; }
2. 建立关系
对于给定的两个节点,我们发现,如果要连接两个节点所在的树,只能改变根节点。所以,我们先构建方法寻找根节点,再将一颗树的根节点连接到另一棵树的根节点上。
int find(int x) { //1. 递归方式 return pre[x] == x ? x : find(pre[x]) //2. 非递归 while(pre[x]^x) x = pre[x]; return x; }
连接函数
void merge(int x, int y) { x = find(x), y = find(y); pre[x] = y; }
例题分析
来源:洛谷P3367
1. 并查集(无优化)
#include <iostream> using namespace std; const int N = 10e5 + 9; int pre[N]; int find(int x) { while (pre[x] ^ x) x = pre[x]; return x; } void merge(int x, int y) { x = find(x), y = find(y); pre[x] = y; } void solve() { int n, m; cin >> n >> m; for (int i = 0; i < N; i++) pre[i] = i; while (m--) { int z, x, y; cin >> z >> x >> y; if (z == 1) { merge(x, y); } else { cout << (find(x) == find(y) ? 'Y' : 'N') << "\n"; } } } int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int _ = 1; while (_--) solve(); return 0; }
2. 路径压缩
当我们每一次查找x的根节点的时候,顺便将x的父节点的根节点也变成根节点,使得生成的树的形状又矮又胖。
只需要修改find函数
int find(int x) { return pre[x] == x ? x : pre[x] = find(pre[x]); }
或者为使用两次while循环来改变。
3. 按秩合并
由上面的分析我们知道,如果是将一颗小树附加到一颗大树上面,那么在查找的过程中的复杂度会降低,以此,我们构建一个rank数组,初始值都为1,它记录这棵树的层数(只有根节点的数有效,毕竟我们只连接根节点)
注意,当我们使用按秩合并的时候,我们在查找的时候就不能进行路径压缩(这样会导致秩不断在改变,我尝试了一下一起使用,效果反而不如单个使用)。
修改的merge函数为:
void merge(int x, int y) { x = find(x), y = find(y); if (x == y) return; if (rnk[x] >= rnk[y]) pre[y] = x, rnk[x]++; else pre[y] = x, rnk[y]++; }
4. 按大小合并
和秩一样,当一颗较小的树合并到另一棵较大的树的时候,形成的树会变得矮胖。因此,创建一个siz数组来储存每棵树的大小,初始值为1。和上面一样,只需要修改为:
void merge(int x, int y) { x = find(x), y = find(y); if (x == y) return; if (siz[x] >= siz[y]) pre[y] = x, siz[x] += siz[y]; else pre[y] = x, siz[y] += siz[x]; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报