关于树的重心--POJ 1655

树的重心的定义:

在一棵树中,找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。

通俗来说就是以这个点为根节点,找到他最大的衣蛾子树,然后让这个子树最小。

例题加模板:

POJ 1655

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int N=2E4+7;
vector<int >ve[N];
bool mark[N];

int ans=N,pos;
int n;

int dfs(int x){
    mark[x]=1;
    int sum=0;//sum为以x为根节点,其包含的点的总数目。
    int s=0;
    for(int i=0;i<ve[x].size();i++){
        if(mark[ve[x][i]]) continue ;
        int x1=dfs(ve[x][i]);
        s=max(s,x1);//
        sum+=x1;
    }
    s=max(s,n-sum-1);//以x为根节点,s是X下边的点集的最大值,n-sum-1是x点上边的点集的最大值
//  ans=min(ans,s);//最大子树最小if(s<=ans){
        if(s==ans){
            pos=min(pos,x);
        }
        else {
            ans=s;
            pos=x;
        }
    }
    return sum+1;
}
void solve()
{
    ans=N;
    memset(mark,0,sizeof mark);
    cin>>n;
    int x,y;
    for(int i=1;i<=n;i++) ve[i].clear();
    for(int i=1;i<=n-1;i++){
        cin>>x>>y;
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    dfs(1);
    cout<<pos<<" "<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(0);
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}

 树的重心的一些性质:

1 树上所有的点到重心的距离和最小,可能会有两个重心,此时到这两个重心的距离和最小

2 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
3 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。

4 一棵树最多有两个重心,并且这两个重心相邻

原文地址:https://www.cnblogs.com/Accepting/p/11848303.html