树的重心

树的重心

本文介绍了树的重心及其性质、如何动态维护修改权值的带权重心、如何寻找断边再加边的带权重心。


无根树的重心定义为:

x 为树根,有 yx 相邻,使得 y 的子树大小的最大值最小,这样的 x 即树的重心。

重心有 1 个 或 2 个,若有 2 个则这 2 个重心相邻。

性质

以重心为根,任意一个它的儿子的子树大小不超过 n/2

树中所有点到一个点的距离和中,到重心的最小。

根据性质,我们可以得出:

如果有一条边 (x,y),将这条边割开,若 x 的子树大小大于 y 的子树大小,则重心在子树 x 中,反之在 y 中,若相等,则 x,y 恰好是两个重心。

同时,若在树上添加一个叶子,则重心最多移动一条边。

求法

扫一遍树求子树大小,根据定义即可求。

假定一个根 rt,则一个点的值即 max(szsonx,szrtszx),这个值最小点就是重心。

应用

点分治:

由于重心的子树大小不超过一半,则可以把树按重心分开,再把分开的每个连通子树递归处理,最多分 O(logn) 层。

则所有重心的子树大小和是 O(logn) 的,我们在这些重心上可以方便地计算路径等信息。

带权重心

每个点有权值,将上面定义中的子树大小换为权值和即为带权重心的定义。

依旧有性质:

如果有一条边 (x,y),将这条边割开,若 x 的子树大小大于 y 的子树大小,则重心在子树 x 中,反之在 y 中。

若相等则需依照 x,y 的权值判断重心,相等则都为重心,否则谁大谁为重心。

可看出:若点权都不相等,则重心唯一。

根据性质动态维护区间修改权值的带权重心 O(dlog2n)

我们上面的性质结合点分治的思想:

先求出点分治的那些重心,从整颗树的重心开始,考虑移动。

若有子树满足性质,显然最多一个子树满足性质,则移动到连通子树的重心(无权重心)。

若没有,则当前点就是带权重心。

如果可以 O(logn) 查询子树权值和,则可以 O(dlog2n) 得到重心,其中 d 为点的度数。

参考例题:ZJOI2015 幻想乡战略游戏

这道题找到重心后用动态点分治即可计算答案。

带权重心的神奇性质

与距离结合

从树上的任意一点作为起点,到树上所有点的距离乘上的终点点权,使它和最小的起点一定是树的带权重心。

值得一提的是如果乘的是 distk 依然成立。

证明

当前在重心 x 上,则若有一条边 (x,y),设 x 侧权值和为 sxy 侧为 sy

考虑转移到 y,则多的贡献为 sxsy,由于重心,sxsy,因此 y 不优。

对于 distk 的情况可感性理解。

与 dfs 序上的带权中点结合

给定根,这里的重心是深度最小的重心。

首先建 dfs 序。

则将节点按 dfs 排列,这上面的带权中点在重心的子树内。

带权中点:将序列上权值求前缀和,第一个大于总权值和一半的点。

证明

深度最小的重心 G 的子树和 szG 大于 sum/2

考虑 dfs 序 dfnG 之前的点的权值和,一定小于 sum/2

同时考虑 dfnG 之后且不在 G 子树内的点的权值和,也一定小于 sum/2

带权中点不在前也不在后,而在中间的子树内。

用带权中点 O(log2n) 动态维护区间修改权值的带权重心

同样的,这里的重心是深度最小的重心。

我们的区间修改权值显然是需要树剖的,我们的 dfn 要在树剖上建。

根据性质,找到带权中点,可以在线段树上二分,O(logn)

找到带权中点后,考虑倍增跳它的父亲。

由于此时我们所求的重心是子树大小 sz>sum/2 中深度最大的点,

于是考虑像倍增 LCA 那样,找到最远的在重心下面的点,重心就是它的父亲。

对于一个点 xszxsum/2,则它在我们的重心下面,于是往上跳。

最后取 fax,0 即可。

注意特判一下如果最开始的点 sz>sum/2,则它就是重心。

我们每次 O(logn) 求子树大小,跳 O(logn) 次,于是就是 O(log2n)

例题:JZOJ 7469 数据结构

断边再加边的带权重心

如果我们断掉一条边 (p,q),再加上一条边 (u,v),考虑带权重心怎么变化。

首先新的图还是树的条件是:
假定 fap=q,同时记 lu=lca(p,u),lv=lca(p,v),形成的新图为树的充要条件为 [p=lu][p=lv]=1

然后考虑带权重心怎么变化,我们已经求出了改变前的带权重心 Rt,我们以它为根给树确定方向。

假定 lca(u,p)=p,那么如果 lca(v,p)=Rt,则新的带权重心在 (v,Rt) 这条路径上。
我们倍增从 v 开始跳,设 sxx 的子树权值和,如果 s[fax,j]+s[p]sum/2 则说明重心还在 fax,j 往上。
最后跳到 fax,0。注意如果 sv+sp>sum/2 则说明 v 已经是重心了。

而如果 lca(v,p)Rt,则相当于边的修改是在同一个子树内完成的,它并不影响整个树的重心,因此重心还是 Rt。

例题:信友队 NOIP2024 模拟 2024.11.25 场。

posted @   dengchengyu  阅读(137)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示