P1395 会议(树的重心)

Posted CCSU_Cola

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1395 会议(树的重心)相关的知识,希望对你有一定的参考价值。

题目链接

有一个村庄居住着 n 个村民,有 n-1 条路径使得这 n 个村民的家联通,每条路径的长度都为 1。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。

题意:找到树的重心,然后求所有点到树的重心的距离和。

思路:树形dp根据重心的性质找到重心,然后再跑dfs求距离和。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100100;
struct node{
    int x,to;
};
node e[maxn];
int idx=0;
int n,h[maxn],f[maxn],siz[maxn];
void add(int a,int b){
    e[idx].x=b,e[idx].to=h[a],h[a]=idx++;
}
void dfs(int x,int fa){
    siz[x]=1;
    for(int i=h[x];i!=-1;i=e[i].to){
        int j=e[i].x;
        if(j==fa)continue;
        dfs(j,x);
        siz[x]+=siz[j];
        f[x]=max(f[x],siz[j]);//最大的儿子子树
    }
    f[x]=max(f[x],n-siz[x]);//与dfs的上面部分取max,因为上面部分也是子树
}
int res=0;
void dfs1(int x,int fa,int step){
    res+=step;
    for(int i=h[x];i!=-1;i=e[i].to){
        int j=e[i].x;
        if(j==fa)continue;
        dfs1(j,x,step+1);
    }
}
int main(){
    memset(h,-1,sizeof h);
    scanf("%d",&n);
    int a,b;
    for(int i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    dfs(1,-1);//找重心
    int pos=1;
    for(int i=2;i<=n;i++){
        if(f[i]<f[pos]){//拿掉该点后子树最小的为重心
            pos=i;
        }
    }
    dfs1(pos,-1,0);
    cout<<pos<<" "<<res<<endl;
}

以上是关于P1395 会议(树的重心)的主要内容,如果未能解决你的问题,请参考以下文章

P1395 会议(树的重心)

AcWing 846. 树的重心

POJ 1655 Balancing Act (树的重心)

HDU6567树的重心换根DP

树的重心及直径

求树的重心