补档树的重心
定义
对于无根树上的每一个点,计算其所有子树中最大的子树节点数,这个值最小的点就是这棵树的重心
特性
- 树的重心至少一个最多两个,如果是两个它俩相邻。
- 以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。
- 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。
- 把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。
- 在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int sz[N], weight[N], centroid[2];
int cnt = 0; void dfs(int rt, int from) { sz[rt] = w[rt]; weight[rt] = 0; for (auto v : tree[rt]) { if (v == from) continue; dfs(v, rt); sz[rt] += sz[v]; weight[rt] = max(weight[rt], sz[v]); } weight[rt] = max(weight[rt], tot - sz[rt]); if (weight[rt] <= (tot >> 1)) centroid[cnt++] = rt; }
|