ACM入门之树的重心
Posted 辉小歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM入门之树的重心相关的知识,希望对你有一定的参考价值。
树的重心的定义:
对于树上的每一个点,计算其所有子树中最大的子树节点数,这个值最小的点就是这棵树的重心。
树的重心的性质:
- 树中所有点到某个点的距离和中,到
重心的距离和是最小的
。如果有两个重心,那么到它们的距离和一样。 - 以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。
- 两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。
在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
例题一:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*3+10;
int h[N],e[N],ne[N],idx;
void add(int a,int b)
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
int st[N],dist[N],n,m,ans=1e9;
int dfs(int u)
st[u]=1;
int sum=0,maxv=0;//是总的子树点的个数,最大的子树个数
for(int i=h[u];i!=-1;i=ne[i])
int j=e[i];
if(st[j]) continue;
int temp=dfs(j);
sum+=temp,maxv=max(maxv,temp);
maxv=max(maxv,n-sum-1);
dist[u]=maxv;
ans=min(ans,maxv);
return sum+1;
int main(void)
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++)
int a,b; cin>>a>>b;
add(a,b),add(b,a);
dfs(1);
for(int i=1;i<=n;i++) if(dist[i]==ans) cout<<i<<" ";
return 0;
例题二:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
int h[N],e[N],ne[N],idx,st[N];
int n,ans=1e9;
void add(int a,int b)
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
int dfs(int u)
int sum=0,maxv=0;
st[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
int j=e[i];
if(st[j]) continue;
int temp=dfs(j);
sum+=temp;
maxv=max(maxv,temp);
maxv=max(maxv,n-sum-1);
ans=min(ans,maxv);
return sum+1;
int main(void)
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=n-1;i++)
int a,b; cin>>a>>b;
add(a,b),add(b,a);
dfs(1);
cout<<ans<<endl;
return 0;
以上是关于ACM入门之树的重心的主要内容,如果未能解决你的问题,请参考以下文章