本文以codeforces EDU Disjoint Sets Union为资料
content
introduction
Disjoint Sets Union
DSU是一种支持对
n
n
n个元素进行
g
e
t
\bm{get}
get和
u
n
i
o
n
\bm{union}
union的数据结构,
g
e
t
(
a
)
\bm{get(a)}
get(a)表示获取
a
\bm{a}
a所属的集合。
u
n
i
o
n
(
a
,
b
)
\bm{union(a,\ b)}
union(a, b)表示合并
a
,
b
\bm{a,\ b}
a, b所属的集合。
DSU使用
p
[
i
]
\bm{p[i]}
p[i]表示
i
\bm{i}
i所属的集合,那么
u
n
i
o
n
(
a
,
b
)
\bm{union(a,\ b)}
union(a, b)可以用
a
\bm{a}
a指向的头结点指向
b
\bm{b}
b指向的头结点,通过使用链的方式合并。一个有效降低时间复杂度的方法是对半,令
r
[
i
]
\bm{r[i]}
r[i]表示
i
\bm{i}
i的阶,那么用低阶指向高阶可以使时间复杂度降为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)。
符合结合性和交换性的运算可以在
u
n
i
o
n
\bm{union}
union时计算,例如
s
u
m
o
r
m
i
n
\bm{sum}\ or\ \bm{min}
sum or min。
problems & solutions
C. Experience
u n i o n ( a , b ) \bm{union(a,\ b)} union(a, b)时,在低阶的extra上减去一个高阶的sum,这样,在从叶子结点到根节点的过程中,不属于当前节点的exp能被extra消去。
D. Cutting a graph
逆向,从后往前加边考虑。
E. Monkeys
逆向。一个解决1为根的方法是增加 m i n \bm{min} min函数。当 u n i o n ( a , b ) \bm{union(a,\ b)} union(a, b)其中有一个集合含1时,更新另一个节点的 t i m e time time,表示在当前时刻两个集合脱离(从前往后看)。考虑到一个集合对应的根节点指向另一个根节点时,最多会更新一次,那么这个方法是可行的。最后扫描所有点,访问其最近 t i m e time time存在的根节点,其 t i m e time time即为该根下所有点(不包含子根)脱离的时刻。一个方法是采取类似 g e t \bm{get} get的更新过程。