3.2 Link-Cut Trees 的 操作
3.2.1 Access
ACCESS 操作是 Link-Cut Trees 的所有操作的基础 . 假设调用了过程 ACCESS (v), 那么从点 v 到根结
点的路径就成为一条新的 Preferred Path. 如果路径上经过的某个结点 u 并不是它的父亲 parent (u) 的 Pre-
ferred Child, 那么由于 parent (u) 的 Preferred Child 会变为 u , 原本包含 parent (u) 的 Preferred Path 将
不再包含结点 parent (u) 及其之上的部分 .
下图为 Link-Cut Trees 的一个结构示意图 , 及一次 ACCESS 操作的前后对比图 .
一棵树
ACCESS (N ) 以后 ACCESS (N ) 之前的 Link-Cut Trees
细边为 Path Parent 边,
粗边为 Auxiliary Tree
上的边
A
B C
D E F G
H
I J
K L M
N
O
A
B C
D E F G
H
I J
K L M
N
O
A
B
C
D EF
G
H
I
JK
L
MN
O
粗边为 Preferred Edge, 细边为普通边
图 1: 一棵树及其 Link-Cut Trees, 以及一次 ACCESS 操作的前后对比
ACCESS 的操作有些出人意料 , 就是直接更新需要被更新的 Auxiliary Tree. 这看起来并不怎么高效 ,
但事实上 , 在后面我们将证明它的时间复杂度是均摊 O(log n ) 的.
首先 , 由于访问了点 v, 那么它的 Preferred Child 应当消失 . 先将点 v 旋转到它所属的 Auxiliary
Tree 的根 , 如果 v 在 v 所属的 Auxiliary Tree 中有右儿子 ( 也就是 v 原来的 Preferred Child), 那么应
该将 v 在 v 所属的 Auxiliary Tree 中的右子树 (对应着它的原来的 Preferred Child 之下的 Preferred
Path) 从 v 所属的 Auxiliary Tree 中分离 , 并设置这个新的 Auxiliary Tree 的 Path Parent 为 v.
然后, 如果点 v 所属的 Preferred Path 并不包含根结点 , 设它的 Path Parent 为 u, 那么需要将 u 旋转
到 u 所属的 Auxiliary Tree 的根 , 并用点 v 所属的 Auxiliary Tree 替换到点 u 所属的 Auxiliary Tree 中
点 u 的右子树 , 再将原来点 u 所属的 Auxiliary Tree 中点 u 的右子树的 Path Parent 设置为 u. 如此操作 ,
直到到达包含根结点的 Preferred Path.
3.2.2 Find Root
在 ACCESS ( v) 之后 , 根结点一定是 v 所属的 Auxiliary Tree 的最小结点 . 我们先把 v 旋转到它所属
的 Auxiliary Tree 的根 . 再从 v 开始 , 沿着 Auxiliary Tree 向左走 , 直到不能再向左 , 这个点就是我们要找
的根结点 . 由于使用的是 Splay Tree 数据结构保存 Auxiliary Tree, 我们还需要对根结点进行 Splay 操作 .
3.2.3 Cut
先访问 v, 然后把 v 旋转到它所属的 Auxiliary Tree 的根 , 然后再断开 v 在它的所属 Auxiliary Tree 中
与它的左子树的连接 , 并设置 .
3.2.4 Join
先访问 v , 然后修改 v 所属的 Auxiliary Tree 的 Path Parent 为 w, 然后再次访问 v .
3