虚树学习笔记
构建方法1
- 将所有点按照
dfs
序排序 - 每次添加一个结点,维护最右链
- 注意分类讨论
- 其实上面的话说了=没说,看别人的题解更明白(不过其实看代码就能大概看懂qwq
inline void Ins(int u) {
if (top == 0) {
stk[++top] = u;
return ;
}
int anc = Lca(stk[top], u);
while (top >= 2 && dep[anc] < dep[stk[top - 1]]) {
V.Add(stk[top - 1], stk[top]);
--top;
}
if (dep[stk[top]] > dep[anc]) V.Add(stk[top--], anc);
if (!top || stk[top] != anc)
stk[++top] = anc;
stk[++top] = u;
}
构建方法2
- 将所有点按照
dfs
序排序 - 对于相邻点,求个
lca
,和原来的点混起来再排序 - 每个结点在虚树上的父亲就是他和前一个点的
lca
正确性是这样的:如果设第二步的点集为 (s) ,那么 (s) 中包含所有虚树上应该有的点。因为虚树上任何一个非关键点(给定的结点成为关键点,不是给定节点而是给定节点的lca
的点就是非关键点)都是某两个关键点的 lca
(否则就不会出现在虚树上),而且在虚树上必然有两个儿子。第一个子树的 dfn
最大的点和第二个子树 dfn
最小的点的 lca
就是这个点。所以任何一个点都会被弄进去。第三步正确性也差不多。
代码很好写。