并查集
解决元素分组问题
不相交的集合,两种操作
1.合并(Union)
2.查找(Find)
实现
-
初始化
fa
数组记录父节点,初始化时父节点为自己
for i in range(n):
fa[i] = i
-
查询
递归访问知道父节,父节点的父节点为自己,即
fa[x] == x
def find(x):
if fa[x] == x:
return x
else:
return find(fa[x])
-
合并
找到两个集合的代表元素,将前者的父节点设为后者
fa[find(i)] = find(j)
效率提升
-
路径压缩
希望每个元素到根节点的路径尽可能短
在查询过程中,将沿途的每个节点的父节点都设为根节点
def find(x):
if fa[x] == x:
return x
else:
fa[x] == find(fa[x])
return fa[x]
-
效率的进一步提升(
rank
的引入)把简单的树往复杂的树上合并,使合并后到根节点距离变长的节点数少
用数组
rank
记录每个根节点对应的树的深度,初始时所有元素的rank
为1,合并时比较两个根节点,把
rank
较小者往较大者上合并按
rank
合并def merge(i, j): x = find(i) y = find(j) if rank[x] <= rank[y]: fa[x] = y else: fa[y] = x if rank[x] == rank[y] and x != y: rank[y] += 1