并查集有两种操作——查询,合并。
查询通常用来求联通块中各节点的父节点。
而合并则可统一两点的父节点。
初始化
1
2
3
4
5int f[N];
for(int i = 0;i<n;i++){
//每个元素都是单独的一个集合,则他们的根都是自己
f[i] = i;
}
查询x的根节点
1
2
3int find(int x){
return f[x] == x ? x : (f[x]=find(f[x]));
}这个三目表达式
f[x] == x
,判断x
的父节点是不是他自己,如果是,x
就是根可以返回find(f[x])
,若x
还有父亲,则查找x
的父亲的父亲,直到有一个点的父亲是自己f[x] = find(f[x])
,便于后续找根:将x
的父亲重置为x
的父亲的父亲,最终x
的父亲就是x
的根合并
1
2
3
4
5
6
7
8
9
10//其实不用刻意写函数,直接在主函数中写亦可
void unionSet(int x, int y) {
x = find(x);
y = find(y);
//若x与y有共同的根,说明x和y在同一个集合里
if (x == y) return;
//令x和y有相同的根
fa[x] = y;
return;
}