概括:
主要是处理不相交集合的合并问题
复杂度:O(logn)
经典应用:
(1)连通图
(2)最小生成树Kruskal算法
(3)最近公共祖先(LCA)
模板:
struct DSU{
vector<int>s,siz;
DSU(){}
DSU(int n){
s.resize(n+1);
iota(s.begin(),s.end(),0);
siz.resize(n+1,1);
}
int find(int u){
return s[u]==u?u:s[u]=find(s[u]);
}
bool merge(int x, int y){
x=find(x);
y=find(y);
if(x==y)return false;
if(siz[x]<siz[y])swap(x,y);
s[y]=x;
siz[x]+=siz[y];
return true;
}
int size(int x){
return siz[find(x)];
}
};
模板解释:
使用:
直接使用结构体调用即可
DSU dsu(n);
find:
find用了路径压缩优化
作用就是防止退化成链
如图:
merge:
用了按枝合并的优化
始终保持树的结构
siz数组就是子节点以及本身的节点个数
相当于是小集合向大集合合并
size:
找到根节点,根节点的节点个数就是当前集合的大小
并查集典题(课后练习题):
模板题:
P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P1111 修复公路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题解:贪心,按照修路时间排序,先把时间短的修了,然后依次合并,最后看是否合并完即可
题解:统计一个集合中的人数,一个集合中2个人可以成为一组:C(n,2),用可以形成的所有关系减去现在已经有的关系
E-小红的树上赋值(easy)_牛客周赛 Round 41 (nowcoder.com)
F-小红的树上赋值(hard)_牛客周赛 Round 41 (nowcoder.com)
题解:启发式合并,将'W'合并 -> 尽可能形成以'R'为根节点的子树,先放负数再放正数,未凑够则反悔