[Luogu2986] [USACO10MAR] great cows gather [gravity dynamic programming dp tree tree]

P2986 [USACO10MAR] great gathering cows

The center of gravity of the tree: find a point, the largest sub-tree nodes least all of its sub-tree, then the tree's center of gravity is the point, after deleting the center of gravity to produce more trees as balanced as possible

nature:

  • Tree in the distance and all points of a point, and the distance to the center of gravity is minimal, if there are two distances and their distance and the same
  • The two trees are connected by an edge, the center of gravity of the two trees original connection new center of gravity in the tree
  • A tree add or delete a node, the center of gravity moves up the tree only one side position of
  • The center of gravity of a tree has at most two, and adjacent

N can have points of view is divided into n node concluded to find the center of gravity!

And then seek the answer

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)<(y)?(y):(x)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
const int N=100000+5,M=1000000+5,inf=0x3f3f3f3f,P=9999973;
int n,sum=0,a[N],size[N],mxs[N],dis[N];
int max_part=inf,zx;
ll ans=0;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,w,nxt;}e[N<<1];
void add(int u,int v,int w){
    e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}

void dfs(int u,int fa){
    size[u]=a[u];
    int maxsize=0;
    for(int i=head[u];i;i=e[i].nxt){
        if(e[i].v==fa) continue;
        dfs(e[i].v,u);
        size[u]+=size[e[i].v];
        maxsize=Max(maxsize,size[e[i].v]);
    }
    maxsize=Max(maxsize,sum-size[u]);
    if(maxsize<max_part) max_part=maxsize,zx=u;
}

void dfs2(int u,int fa){
    for(int i=head[u];i;i=e[i].nxt)
    if(e[i].v!=fa) dis[e[i].v]=dis[u]+e[i].w,dfs2(e[i].v,u);
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i]),sum+=a[i];
    for(int i=1,u,v,w;i<n;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
    dfs(1,0);
    dis[zx]=0;
    dfs2(zx,0);
    for(int i=1;i<=n;++i) ans+=(ll)dis[i]*a[i];
    printf("%lld",ans);
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/lxyyyy/p/11209690.html