【学习笔记】虚树
简介
虚树就是一种很无奈时的无赖做法
--唐末
当题目中答案只与某些关键点有关,而关键点很稀疏时,就可以用虚树将整棵树浓缩。
建虚树
- 方法一:
二次排序 + LCA 连边
- 将所有关键点按 dfn 序排序,求出相邻两个点的 LCA(确定虚树中的所有点)。
- 将所有 LCA 及关键点去重并再次按 dfn 序排序。
- 算出相邻两个点 x,y 的 LCA 并与 y 连边。
证明:若 x 为 y 的祖先,即 y 是 x 的第一个儿子,由于 dfn 序相邻,所以两者之间无其它点,所以只会被他们相连。
若 x 不为祖先,即 y 不是 LCA 的第一个儿子,由于 dfn 序相邻,所以 y 到 LCA 之间无其他点。
性质:可以发现,每两个关键点最多会生成一个虚点,所以算上钦定的根节点 1,虚树上最多会有关键点数 \(\times 2\) 个节点(类似满二叉树)。
- 方法二
单调栈
首先单调栈维护的是虚树中的一条链。
- 将 1 节点压入栈,并将所有关键点按 dfn 序排序。
- 将排好序的点逐个加入栈:
求出当前点 x 与栈顶结点 y 的 LCA 节点 l,
若 y 就是 l,说明 x 与 y 在一条链上,直接把两个点连起来就行;
若 l 不是栈顶结点,说明不在同一条链上,就将多余的点弹掉(并同时连边),并判断 l 是否在栈内,若不在就压入栈(具体步骤看 OIwiki)。 - 将还在栈内的点弹掉并连边。

浙公网安备 33010602011771号