【学习笔记】虚树

虚树学习笔记

洛谷日报

构建方法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 就是这个点。所以任何一个点都会被弄进去。第三步正确性也差不多。

代码很好写。

你可能感兴趣的:(【学习笔记】虚树)