【模板】树的重心

树的重心是指使得最大子树结点数最小的点,具有多个性质,例如所有点到重心的距离和最小。在无权树中,以重心为根的所有子树大小不超过一半。本文讨论了如何找到树的重心,包括处理含有两个重心的情况,并提供了Codeforces和ICPC亚洲徐州区域赛的例题分析。
摘要由CSDN通过智能技术生成

树的重心

树的重心也叫树的质心。对于一棵树n个节点的无根树,找到一个点,使得把树变成以该点为根的有根树时,最大子树的结点数最小。换句话说,删除这个点后最大连通块(一定是树)的结点数最小。

性质:

  1. 树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个重心,他们的距离和一样。
  2. 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
  3. 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
  4. 一棵树最多有两个重心,且相邻。
  5. 对于无权树,以重心为根,所有子树的大小都不超过整棵树大小的一半,即其所有子树大小 ≤ N / 2 \le N/2 N/2

带权树的重心:https://www.cnblogs.com/knife-rose/p/11258403.html

int T, n;
const int maxn = 1e5+7;
int sz[maxn], hs[maxn];
// sz[i]表示以i为根的子树的大小, hs[i]表示以i为根的重儿子(最大子树)的大小

struct edge{
   
    int next, v;
}e[maxn*2];
int cnt = 0;
int head[maxn];

int cent[2] = {
   0, 0}; // 重心
int ccnt = 0; // 重心个数

 
void addedge(int u, int v)
{
   
    e[cnt] = edge{
   head[u], v};
    head[u] = cnt++;
    e[cnt] = edge{
   head[v], u};
    head[v] = cnt++;
}
 
void dfs(int u, int fa)
{
   
    sz[u] = 1;
    hs[u] = 0;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
   
        int v = e[i].v;
        if(v!=fa)
        {
   
            dfs(v, u);
            sz[u] += sz[v];
            hs[u] = max(hs[u], sz[v]);
            //cout << u << ' ' << v << ' ' << b[u] << endl;
        }
    }
    hs[u] = max(hs[u], n-sz[u]);
    if (hs[u] <= n / 2) {
     // 依照树的重心的定义统计
    	cent[ccnt++] = cur;
  }
}

例题

Codeforces-Link Cut Tree
题目给定一棵树,要求删除一个边,再连接一条边,将其变为只有一个重心的树。

若只有一个重心则只需要把任意一个边断开连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值