2021寒假ACM集训—Jaelyn的纪要
##第二天-----并查集
1.初始化
int fa[MAXN];
inline void init(int n)
{
for (int i = 1; i <= n; ++i)
fa[i] = i;
}
让数组中每个元素的值等于下标值
2.合并
inline void merge(int i, int j)
{
fa[find(i)] = find(j);
}
合并操作也是很简单的,先找到两个集合的代表元素,然后将前者的父节点设为后者即可。当然也可以将后者的父节点设为前者.
3.查询
int find(int x)
{
if(fa[x] == x)
return x;
else
return find(fa[x]);
}
//返回一个值的根节点
4.合并(路径压缩)
int find(int x)
{
if(x == fa[x])
return x;
else{
fa[x] = find(fa[x]); //父节点设为根节点
return fa[x]; //返回父节点
}
}
等同于:
int find(int x)
{
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
初始化(按秩合并)
inline void init(int n)
{
for (int i = 1; i <= n; ++i)
{
fa[i] = i;
rank[i] = 1;
}
}
合并(按秩合并)
inline void merge(int i, int j)
{
int x = find(i), y = find(j); //先找到两个根节点
if (rank[x] <= rank[y])
fa[x] = y;
else
fa[y] = x;
if (rank[x] == rank[y] && x != y)
rank[y]++;
//如果深度相同且根节点不同,则新的根节点的深度+1
}