【Codeforces Round #268(Div 1)】Tree

Description

有一棵树, d(u,v) 表示 u v之间最短距离。
现在要求一个排列 pi ,使得 ni=1d(i,pi) 最大,同时满足最大时字典序最小。

Solution

对于一条边,我们肯定希望它被计算尽量多次,若左右端点连出去的节点个数分别为 x ,y,那么该边的最大贡献为 val×min(x,y)×2 ,于是选择重心来构造恰好能满足(如下)。

先把式子写出来:

i=1nd(i,pi)=i=1n(depi+deppi2deplca(i,pi))=2i=1ndepii=1n2deplca(i,pi)

选定一个根,每对点不能出现在根直接连下去的同一棵子树中。
对于根直接连向的每棵子树,设大小为 k ,子树内的点可以和子树外的nk个点匹配,同时这 k 个点都要被匹配,那么knk kn2 。那么选择树的重心为根就能满足。

于是我们抛开权值,只用找字典序最小的排列。

对于当前将要匹配 i ,要找到最小的pi,同时满足不同根直属子树。设当前子树有 x 个未匹配的(即编号大于i的个数),以及有 y 个未被匹配的(在这棵子树中不出现在已确定pi中的编号),那么满足 xni+1y ,即 x+yni+1 。对于一棵子树满足 x+y=ni+1 ,那么当 i+1 时, x y要减 1 。此时分两种情况:

  1. i在这棵子树内,那么可以直接和子树外的匹配,使得 x1

    • i 不在这棵子树内,那么必须选择这棵子树内的匹配,使得y1
    • 若当前没有满足等式的情况,直接选择与 i 不同子树匹配即可。
      (对于每次匹配,选择编号最小的)
      至于重心,当满足等式时,那么必须选择那棵子树,如不满足,则匹配最小编号(可以匹配自己)。

      于是可以用线段树维护,对每个子树开一个位置,存储x y <script type="math/tex" id="MathJax-Element-2518">y</script>,以及被匹配了多少个。

posted @ 2017-12-08 22:15  sadstone  阅读(34)  评论(0编辑  收藏  举报