WIKIOI
wiki(I:)
比赛相关
工具软件
语言基础
算法基础
搜索
动态规划
字符串
数学
数据结构
图论
计算几何
杂项
专题
图论部分简介
图论相关概念
图的存储
DFS(图论)
BFS(图论)
树基础
树的直径
最近公共祖先
树的重心
树链剖分
树上启发式合并
虚树
树分治
动态树分治
AHU算法
树哈希
矩阵树定理
有向无环图
拓扑排序
最小生成树
斯坦纳树
最小树形图
最小直径生成树
最短路
拆点
差分约束
k 短路
同余最短路
强连通分量
双连通分量
割点和桥
2-SAT
欧拉图
哈密顿图
二分图
最小环
平面图
图的着色
网络流简介
最大流
最小割
费用流
上下界网络流
Prufer 序列
LGV 引理
弦图
46 objects
本站非官方,所收集资源均来源于网络。
树的重心 - 图论
author: Ir1d, TrisolarisHD, LucienShui, Anguei, H-J-Granger ## 定义 对于树上的每一个点,计算其所有子树中最大的子树节点数,这个值最小的点就是这棵树的重心。 (这里以及下文中的“子树”都是指无根树的子树,即包括“向上”的那棵子树,并且不包括整棵树自身。) ## 性质 以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。 把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。 在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。 ## 求法 在 DFS 中计算每个子树的大小,记录“向下”的子树的最大大小,利用总点数 - 当前子树(这里的子树指有根树的子树)的大小得到“向上”的子树的大小,然后就可以依据定义找到重心了。 ### "参考代码" ```cpp // 这份代码默认节点编号从 1 开始,即 i ∈ [1,n] int size[MAXN], // 这个节点的“大小”(所有子树上节点数 + 该节点) weight[MAXN], // 这个节点的“重量” centroid[2]; // 用于记录树的重心(存的是节点编号) void GetCentroid(int cur, int fa) { // cur 表示当前节点 (current) size[cur] = 1; weight[cur] = 0; for (int i = head[cur]; i != -1; i = e[i].nxt) { if (e[i].to != fa) { // e[i].to 表示这条有向边所通向的节点。 GetCentroid(e[i].to, cur); size[cur] += size[e[i].to]; weight[cur] = max(weight[cur], size[e[i].to]); } } weight[cur] = max(weight[cur], n - size[cur]); if (weight[cur] <= n / 2) { // 依照树的重心的定义统计 centroid[centroid[0] != 0] = cur; } } ``` ## 参考
## 习题 - [POJ 1655 Balancing Art](http://poj.org/problem?id=1655) (模板题) - [CodeForces 1406C Link Cut Centroids](https://codeforces.com/contest/1406/problem/C)