虚树教程

Posted chy-2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了虚树教程相关的知识,希望对你有一定的参考价值。

问题引入

SDOI2011消耗战

虚树

按照朴素的做法,就是对于每一个询问都跑一边DP。
\\[ Dp[i] = Dp[ i ] + \\min( Dp[Son],Cost[i,Son]) \\,\\,\\,(Son不为关键点)\\Dp[i] = Dp[ i ] + Cost[ i, Son ] \\,\\,\\,(Son为关键点)\\Dp[i] = INF\\,\\,\\,(i为叶子) \\]
这样时间上显然是不行的。我们需要优化一下。

注意到\\(\\sum k\\leqslant 500000\\),那么可能许多点都不是关键点,而我们却浪费了许多时间在它们上面。其实删掉一个关键点,只需要断掉路径上边权最小的边即可。

这么说来,我们可以缩掉很多不是关键点的点。但是为了保持原树的形状,我们同时需要维护每两个点之间的最近公共祖先(LCA)。其实到这里就可以尝试上手了。下面提供一个可能比较优美的虚树构建方法:

首先按照所有关键点的DFS序排序。开一个 Stack ,加入根节点。

顺序遍历排好序的所有关键点,求关键点和栈顶的Lca。记栈顶元素为Top,栈顶第二个元素为 PreTop(如果有的话)。分为以下几种情况考虑:

  • Deep[ Lca ] = Deep[ Top ]:那么直接把当前点加入 Stack 即可。
  • Deep[ Lca ] < Deep[ Top ] : 如果Deep[ PreTop ] > Deep[ Lca ],则在新树种加入边PreTop-Top,并且弹出栈顶元素,直到 Deep[ PreTop ] <= Deep[ Lca ]。 然后再分两种情况 : 1)如果Deep[ PreTop ] = Deep[ Lca ],在新树种加入PreTop-Top,弹出栈顶,然后加入当前点;2)如果Deep[ PreTop ] = Deep[ Lca ], 在新树种加入Top-Lca,弹出栈顶,然后加入Lca和当前点。
  • 最后顺序弹出栈顶,并同时加入边。

那么构造到此结束了。这样如果预处理了Lca,就可以线性构造虚树了。

开头所提的问题可以参考这里

以上是关于虚树教程的主要内容,如果未能解决你的问题,请参考以下文章

虚树-学习笔记

虚树复习

虚树入门

模板虚树

知识点:虚树

虚树(Bzoj3611: [Heoi2014]大工程)