树的重心
树的重心
本文介绍了树的重心及其性质、如何动态维护修改权值的带权重心、如何寻找断边再加边的带权重心。
无根树的重心定义为:
令
重心有 1 个 或 2 个,若有 2 个则这 2 个重心相邻。
性质
以重心为根,任意一个它的儿子的子树大小不超过
树中所有点到一个点的距离和中,到重心的最小。
根据性质,我们可以得出:
如果有一条边
同时,若在树上添加一个叶子,则重心最多移动一条边。
求法
扫一遍树求子树大小,根据定义即可求。
假定一个根
应用
点分治:
由于重心的子树大小不超过一半,则可以把树按重心分开,再把分开的每个连通子树递归处理,最多分
则所有重心的子树大小和是
带权重心
每个点有权值,将上面定义中的子树大小换为权值和即为带权重心的定义。
依旧有性质:
如果有一条边
若相等则需依照
可看出:若点权都不相等,则重心唯一。
根据性质动态维护区间修改权值的带权重心
我们上面的性质结合点分治的思想:
先求出点分治的那些重心,从整颗树的重心开始,考虑移动。
若有子树满足性质,显然最多一个子树满足性质,则移动到连通子树的重心(无权重心)。
若没有,则当前点就是带权重心。
如果可以
参考例题:ZJOI2015 幻想乡战略游戏
这道题找到重心后用动态点分治即可计算答案。
带权重心的神奇性质
与距离结合
从树上的任意一点作为起点,到树上所有点的距离乘上的终点点权,使它和最小的起点一定是树的带权重心。
值得一提的是如果乘的是
证明
当前在重心
考虑转移到
对于
与 dfs 序上的带权中点结合
给定根,这里的重心是深度最小的重心。
首先建 dfs 序。
则将节点按 dfs 排列,这上面的带权中点在重心的子树内。
带权中点:将序列上权值求前缀和,第一个大于总权值和一半的点。
证明
深度最小的重心
考虑 dfs 序
同时考虑
带权中点不在前也不在后,而在中间的子树内。
用带权中点 动态维护区间修改权值的带权重心
同样的,这里的重心是深度最小的重心。
我们的区间修改权值显然是需要树剖的,我们的
根据性质,找到带权中点,可以在线段树上二分,
找到带权中点后,考虑倍增跳它的父亲。
由于此时我们所求的重心是子树大小
于是考虑像倍增 LCA 那样,找到最远的在重心下面的点,重心就是它的父亲。
对于一个点
最后取
注意特判一下如果最开始的点
我们每次
断边再加边的带权重心
如果我们断掉一条边
首先新的图还是树的条件是:
假定
然后考虑带权重心怎么变化,我们已经求出了改变前的带权重心
假定
我们倍增从
最后跳到
而如果
例题:信友队 NOIP2024 模拟 2024.11.25 场。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下