dfs 序求 lca 学习笔记

作用大概就是一种很好写,而且常数还小的求 lca 的办法。

dfs 序有性质,若 \(u\)\(v\) 祖先则 \(\operatorname{dfn}_u<\operatorname{dfn}_v\)

钦定 \(\operatorname{dfn}_u<\operatorname{dfn}_v\),考虑 \(u\)\(v\) 的最近公共祖先 \(d\) 的两种情况:

  • \(u\)\(v\) 祖先,则这种情况下我们发现 \(u\)\(\operatorname{dfn}_x\in [\operatorname{dfn}_u,\operatorname{dfn}_v]\) 中深度最小的节点 \(x\)

充分性:若 \(u\)\(v\) 祖先,则 \([\operatorname{dfn}_u,\operatorname{dfn}_v]\) 这个区间内肯定都是 \(u\) 子树内的结点,由于 dfs 序的性质不可能有节点比 \(u\) 的深度还小。

必要性类似。

  • \(u\) 不是 \(v\) 祖先,则这种情况下 dfs 序的遍历肯定是 \(d\to u\to d\to v\),但此时我们发现 \([\operatorname{dfn}_u,\operatorname{dfn}_v]\) 这个区间只能包含下图的节点:

发现这段区间肯定会包含一个 \(d\) 的儿子,所以 \(d\) 就是这段区间内深度最小的节点的父节点。


判断 \(u\) 是否为 \(v\) 的祖先其实好搞,但有一个更加优雅的做法。

我们发现这两种情况本质上来讲可以合并成一个情况,即 \(d\)\([\operatorname{dfn}_u+1,\operatorname{dfn}_v]\) 这段区间内深度最小的节点(若有多个,则本质上来讲就是 \(u\to v\) 遍历的路径中间多加了几个 \(d\) 的儿子的子树,随便选一个即可)的父亲。

稍微想想边界情况,证明不难。

然后有了这个性质,就可以 ST 表 \(O(n\log n)\) 预处理和 \(O(1)\) 查询了。

posted @ 2025-09-08 19:51  _E_M_T  阅读(7)  评论(0)    收藏  举报