树的重心

本文深入探讨了树的重心概念,即在一个无根树中找到一个点,使其成为有根树时,最大子树的节点数达到最小。介绍了树重心的四大特性,并提供了一段C++代码实现,用于计算特定树的重心。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树的重心

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

性质

(1)树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
(2)把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
(3)一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
(4)一棵树最多有两个重心,且相邻。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read() /// 读入
{
    char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
    int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    if(k=='-')x=0-x; return x;
}

int n;
int k;

int edge[100050];
int pre[100050];
int last[100050];
int g=0;
int sum[100050];
int maxj[100050];
int minn=INT_MAX;

void dfs(int d,int fa)
{
    for(int i=last[d];i!=0;i=pre[i])
    {
        int z=edge[i];
        if(z!=fa)
        {
            dfs(z,d);
        }
    }
    maxj[d]=max(maxj[d],n-sum[d]-1);  ///  最大后子树 前子树
    minn=min(minn,maxj[d]);
    sum[d]+=1;  ///   加上当前点
    sum[fa]+=sum[d];  /// 加上所有子树 父节点作为子树
    maxj[fa]=max(sum[d],maxj[fa]);  ///  最大后子树
    return;
}
int m;
int main()
{
    n=read();
    m = read();
    int a1,b1;
    for(int i=0;i<m;++i)
    {
        a1=read(),b1=read();
        edge[++g]=b1;
        pre[g]=last[a1];
        last[a1]=g;

        edge[++g]=a1;
        pre[g]=last[b1];
        last[b1]=g;
    }
    dfs(a1,0);
    for(int i=1;i<=n;++i)
    if(maxj[i]==minn)
    cout<<i<<" ";
    cout<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值