zoukankan      html  css  js  c++  java
  • Codeforces 468D Tree

    题目

    给出一棵带边权的树,求一个排列(p),使得(sum_{i=1}^{n}{dis(i, p_i)})的值最大,其中(dis(v, u))表示(v)(u)的距离。

    算法

    这题的思路非常巧妙,又是和重心有关的题目!记得ydc的大树这题的ydc的做法有异曲同工之妙。

    首先我们列答案的计算公式:$$sum_{i=1}^{n}{dep_i+dep_{p_i}-dep_{lca(i,p_i)}}$$
    其中(dep(i))(i)到根的距离,(lca(v,u))就不用说了吧。
    上面的式子等价于$$2 sum_{i=1}{n}{p_i}-sum_{i=1}{n}{dep_{lca(i,p_i)}}$$
    我们就要使(sum_{i=1}^{n}{dep_{lca(i,p_i)}})最小化。

    找到树的重心(root),并使它 变为根,显然我们有一种方法,使得(lca(i,p_i))都是(root),所以答案就是(2 sum_{i=1}^{n}{p_i})

    难点在求字典序最小的排列(p)

    我们可以按(1)(n)的顺序依次确定(p_i),根据贪心,我们每次必然选标号最小的点(j)。而且这个点要满足:

    • (lca(i,j)=root),我们可以把(root)去掉,那么一棵树就裂成了若干“小树”,那么就是要满足(i)(j)不在同一个小树。
    • 仅仅满足上面的条件是不够的,因为有可能出现(i)(j)只能在同一个小树的情况,所以我们要稍加限制:如果某个小树里出现了标号大于i的结点数量+还没有被选的结点数量=(n-i),那么,(i)(j)之一 一定要在这个小树里。

    我的代码

  • 相关阅读:
    mplayer命令行模式下的使用方法
    CentOS安装wireshark
    CentOS查看系统信息
    测试理论1
    单例模式
    接口测试
    rabbitmq
    redis数据库
    时间模块
    charles抓取数据
  • 原文地址:https://www.cnblogs.com/wangck/p/4372793.html
Copyright © 2011-2022 走看看