zoukankan      html  css  js  c++  java
  • 虚树教程

    问题引入

    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 kleqslant 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,就可以线性构造虚树了。

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

  • 相关阅读:
    深度残差网络的理解
    迪士尼收购福克斯,传媒巨头江山瓦解?
    穷人的噩梦:来自金融公司的高利贷
    智能家居沦为家暴的“新工具”?
    墨西哥“死亡选举”导致近 150 名政客被杀
    推荐系统
    多线程编程
    two sum
    python 操作mysql
    天才大猩猩可可去世,享年 46 岁
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11594425.html
Copyright © 2011-2022 走看看