148 字
1 分钟
数据结构-并查集
经典并查集
选择每个集合的头作为该集合的代表
基本操作
- find 查找根节点
- isSameSet 查找是否属于同一个集合
- unite 合并两个集合
优化方法
- 扁平化/路径压缩 (一定要做)
- 小挂大/按秩合并 (可以不做 本质上是秩的概念)
int n;vector<int> father;vector<int> sizes;
void build(){ for(int i=0;i<=n;i++){ father[i]=i; // 一开始每个元素都指向自己 sizes[i]=1; // 一开始每个集合都只存在自己,大小为1 }}
int find(int idx){ stack<int> st; while(idx!=father[idx]){ st.push(idx); idx=father[idx]; } // 实际情况下可以递归简化写法,或者扫两遍 while(!st.empty()){ // 路径压缩/扁平化 father[st.top()]=idx; st.pop(); } return idx;}
int find(int idx){ // 并查集查询操作递归版 if(father[idx]==idx) return idx; return father[idx]=find(father[idx]);}
bool isSameSet(int x,int y){ return find(x)==find(y);}
void unite(int x,int y){ int rx=find(x); int ry=find(y); if(rx!=ry){ // 小挂大 if(sizes[rx]>=sizes[ry]){ sizes[rx]+=sizes[ry]; father[ry]=rx; } else{ sizes[ry]+=sizes[rx]; father[rx]=ry; } }}应用
- 求图的连通分量
例题
P3367 【模板】并查集 - 洛谷
P1536 村村通 - 洛谷
P1196 [NOI2002] 银河英雄传说 - 洛谷
带权并查集
可持久化并查集
可撤销并查集
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时








