树的重心
作者:互联网
一、树的重心的定义:
在一棵树中,如果我们选择某个结点为根,可以使得它的所有子树中最大的子树最小,那么这个结点就被称作这棵树的重心。
二、树重心的性质:
1.以重心为树根时,所有子树的大小不超过全树大小的一半。
2.如果树的所有边权都为1,那么树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。反过来,距离和最小的点一定是重心。
3.把两棵树通过一条边相连得到一棵新的树,则新的重心在较大的一棵树一侧的连接点与原重心之间的简单路径上。如果两棵树大小一样,则重心就是两个连接点。
另外一种说法:把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。
4.在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
5.一颗树最多只有两个重心,且这两个重心一定是相邻的。此时树一定有偶数个节点,且可以被划分为两个大小相等的分支,每个分支各自包含一个重心。
6.一棵树的重心一定在根节点所在的重链上。
7.一棵树的重心一定是以该树根节点重儿子为根的子树的重心的祖先。
8.往树上增加或减少一个叶子,如果原节点数是奇数,那么重心可能增加一个,原重心仍是重心;如果原节点数是偶数,重心可能减少一个,另一个重心仍是重心。
三、找重心
遍历树,对每个点求 \(f_u\) 表示最大子树。边遍历边求最小 \(f_u\)。
代码:
inline void dfs(int u, int fa)
{
sz[u] = 1;
int v;
for(int e = hd[u]; e; e = nt[e])
if((v = to[e]) ^ fa)
{
dfs(v, u);
sz[u] += sz[v];
f[u] = max(f[u], sz[v]);
}
f[u] = max(f[u], n - sz[u]);
if(!ctr || f[u] < f[ctr] || (f[u] == f[ctr] && u < ctr)) ctr = u;
}
标签:sz,子树,重心,ctr,int,一棵树 来源: https://www.cnblogs.com/fakeryu/p/16410984.html