CSP2019 树的重心

题意

给定一棵有编号树,对于每一条边,贡献为将这条边删除后分裂的两棵树重心编号之和(一棵树可能有两个重心被计算)
\(n\le 10^6\)

重心(性质)

定义0.0:对于一棵无根树,节点\(u\)儿子\(u\)的所有相邻节点;对于儿子\(v\),其子树大小为设\(u\)为根时,\(v\)的子树大小;儿子的重量为子树大小。

定义0.1:对于一棵无根树,令\(mx_u\)为节点\(u\)最重的儿子子树节点个数。

定义0.2:对于一棵无根树,对于任意点\(u\),令\(v\)\(u\)最重的儿子。若\(mx_v>mx_u\),则\(u\)重心;若\(mx_v=mx_u\),则\(u,v\)均为重心

定义0.3:对于一棵节点个数为\(n\)的无根树,对于任意点\(u\),若\(mx_u\le \left\lfloor\frac{n}{2}\right\rfloor\),则\(u\)为重心。

推论0.1:对于一棵无根树,选择任意点\(u\),令\(v\)\(u\)最重儿子。若\(mx_v<mx_u\),则令\(u'=v\)。重复此操作,最终停留的节点为重心(若树有两个重心则会在两个间反复横跳)。

推论0.2:对于一棵无根树,\(mx_u\)最小的节点为重心。

推论0.3:对于一棵无根树,若\(u\)有多个重儿子,则\(u\)为重心。

做法(本题)

回到本题上来,将这棵无根树的重心看作根(若有两个重心则将之间的边看作根),下面的树均为有根树。

定义1.1:令\(mx_u\)为节点\(u\)最重的儿子节点,\(root_{u}\)为节点\(u\)子树的重心

结论1.1:对于非叶子节点\(u\)\(root_u\)\(root_{mx_u}\sim u\)路径间

根据结论1.1,对于所有非重心节点\(u\),子树内的重心可以由重儿子转移,均摊\(O(n)\)

根据推论0.2,对于所有非重心节点\(u\),删去\(u\)的子树,重心将会(1)不变、(2)向重心的重儿子移动(3)向重心的次重儿子移动
对于删掉重儿子子树外的子树,重心一定会不变反复向重儿子移动。可以发现具体删掉哪个节点是不重要的,枚举删掉子树大小,均摊\(O(n)\)
对于删掉重儿子子树内的子树,重心一定会不变先向次重儿子移动再向重儿子移动。与上面做法类似,均摊\(O(n)\)

posted @ 2020-11-06 08:57  Grice  阅读(197)  评论(0编辑  收藏  举报