To_Heart—题解——树的重心
解释:
树的重心定义为树的某个节点,当去掉该节点后,树的各个连通分量中,节点数最多的连通分量其节点数达到最小值
思路
首先,我们得明白一个性质:
删除重心后所得的所有子树,节点数不超过原树的1/2;
这不是废话
通过这个性质,我们可以对重心进行求解
树上任选一点i,进行DFS,并统计该点所有子树的大小和以它为根的子树的大小,这样也就可以得到一个点所有子树的大小及的大小,如果它的大小大于了原树的一半,就说明它不是重心
还有一个问题,如果这个点不是根节点,那么删掉后剩下的连通块不止有他的子树,还有他上面的部分,这部分可以由原树所有节点减去他自己的子树大小得到
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=105;
vector<int> v[MAXN];
int dp[MAXN]={};
int cnt[MAXN]={};
int CNT=0,n;
bool f[MAXN]={};
void DP(int x){
dp[x]=1;
bool flag=1;
//printf("%d %d\n",x,dp[x]);
for(int i=0;i<v[x].size();i++){
int y=v[x][i];
if(f[y])
continue;
f[y]=1;
DP(y);
dp[x]+=dp[y];
if(dp[y]>n/2){
flag=0;
}
}
if(n-dp[x]>n/2){
flag=0;
}
if(flag){
cnt[++CNT]=x;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
f[1]=1;
DP(1);
printf("%d\n",CNT);
sort(cnt+1,cnt+CNT+1);
for(int i=1;i<=CNT;i++){
printf("%d\n",cnt[i]);
}
// cout<<endl;
// for(int i=1;i<=n;i++){
// printf("%d ",dp[i]);
// }
return 0;
}

浙公网安备 33010602011771号