并查集 按秩合并&路径压缩
并查集
一种可以动态维护若干个不重叠的集合或无向图的连通块的数据结构。
主要支持以下操作:
find : 查询一个元素属于哪个集合
merge : 合并两个集合
并查集的每个集合都需要一个“爹”来表示这整个集合,所以判断两个元素是否在同一集合,就看他们爹是否相同。
有一个显而易见的初始化,对于要维护的序列,初始每个元素的爹就是他自己,也就是初始化。
inline void init(int n){ for(int i=1;i<=n;++i)fa[i] = i; }
这里直接放上找爹函数,也就是 find 操作,递归完成
inline int findfa(int x){ return fa[x] == x ? x : fa[x] = findfa(fa[x]); }
路径压缩
考虑这样的情况
画的好丑
是不是在找 7 的爹的时候要好久好久,这显然是不能接受的。
这就要用到路径压缩了,怎么压呢?
相信聪明的你已经明白了
我们在合并的时候直接连到爹上去,顺便查找的时候也直接连上去,就OK啦。
也就是说
fa[findfa(x)] = findfa(y);
按秩合并
我们把每个集合看成一个树,记录一个 siz数组维护树的深度,每次将深度小的合并到深度大的,这样可以保证树的最大深度为 logn 这种方法不会破坏树的结构,对于以后学习的撤销操作和可持久化有益。。
观察这两颗树,显然将1接到4下面,树的深度不会增大,但将4接到1下面,树却变深。
当然了,按秩合并顺便路径压缩也是可以的,并且很快
inline void merge(int x,int y){ int u = findfa(x),v = findfa(y); if(u == v)return; if(siz[u] > siz[v])fa[v] = u; else{ if(siz[u] == siz[v])siz[v]++; fa[u] = v; } }
初始的时候 siz 都为 1 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App