51nod 1737【树的重心】

来源:互联网 发布:nokia n9 软件下载 编辑:程序博客网 时间:2024/05/29 03:59
思路:
树的重心也叫树的质心。
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,
生成的多棵树尽可能平衡。
考虑每一条边被统计进答案几次,若断开这条边后树形成大小为s1、s2的两个联通块则这条边最多被统计min(s1,s2)次。

删去重心后任意同一联通块中的两点不构成路径。

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N=1e5+10;struct asd{    LL w;    int to;    int next;}e[N*2];int head[N],tol,n;void init(){    memset(head,-1,sizeof(head));    tol=0;}void add(int u,int v,LL w){    e[tol].w=w;    e[tol].to=v;    e[tol].next=head[u];    head[u]=tol++;}bool vis[N];int d[N];int minnode,minbalence;void DFS(int u,int pre){    d[u]=1;    int maxson=0;    for(int i=head[u];~i;i=e[i].next)    {        int v=e[i].to;        if(vis[v]) continue;        vis[v]=true;        DFS(v,u);        d[u]+=d[v];        maxson=max(maxson,d[v]);    }    maxson=max(maxson,n-d[u]);    if(maxson<minbalence)    {        minbalence=maxson;        minnode=u;    }}LL ans;void DFS_2(int u,LL sum){    for(int i=head[u];~i;i=e[i].next)    {        int v=e[i].to;        if(vis[v]) continue;        vis[v]=true;        ans=ans+sum+e[i].w;        DFS_2(v,sum+e[i].w);    }}int main(){    int u,v;    LL w;    scanf("%d",&n);    init();    for(int i=1;i<n;i++){        scanf("%d%d%lld",&u,&v,&w);        add(u,v,w);        add(v,u,w);    }    minnode=0;    minbalence=INT_MAX;    memset(d,0,sizeof(d));    memset(vis,false,sizeof(vis));    d[1]=0;    vis[1]=true;    DFS(1,0);    memset(vis,false,sizeof(vis));    ans=0;    vis[minnode]=true;    DFS_2(minnode,0LL);    printf("%lld\n",ans);    return 0;}


0 0
原创粉丝点击