树的重心

版权声明: https://blog.csdn.net/zjh_2017/article/details/79517410

树的重心

概念

在树中,必然存在一个或多个点,保证此点相连的结点数最多的连通块的结点数最小,我们把这个点叫做树的“重心”。

这边关键是把几个数组的含义理解好就差不多了。中间的建树自然不用说。dfs遍历跟LCA差不多滴,这个我会,很开心。

linkk是建树时用到的,son[i]存节点i所在的子树大小,f[i]存节点i将树分成的几个联通块中最大的一块的节点数。

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
int n,xx,yy,temp,linkk[maxn],k,son[maxn],f[maxn],ans=2000000000;
struct atree
{
    int y,next;
}
a[maxn];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
void insertt(int ss,int ee)
{
    a[++temp].y=ee;
    a[temp].next=linkk[ss];
    linkk[ss]=temp;
}
void dfs(int t,int father)
{
    son[t]=1;//初始值
    for (int i=linkk[t];i;i=a[i].next)
    {
        int k=a[i].y;
        if (k==father) continue;
        dfs(k,t);
        son[t]+=son[k];//加上子树的节点数
        f[t]=max(f[t],son[k]);//记录最大的联通块节点数
    }
    f[t]=max(f[t],n-son[t]);//计算剩余的一个联通块大小
    ans=min(ans,f[t]);//更新重心
}
int main()
{
    n=read();
    for (int i=1;i<n;++i) 
    {
        xx=read();
        yy=read();
        insertt(xx,yy);
        insertt(yy,xx);
    }
    dfs(1,0);
    for (int i=1;i<=n;++i)
    if (f[i]==ans) printf("%d ",i);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zjh_2017/article/details/79517410