BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会

来源:互联网 发布:策略模式 java的概念 编辑:程序博客网 时间:2024/05/22 12:50

树形dp

首先先一遍dfs撸出以1为集会地点的不方便值以及以各点为根的子节点个数(包括自己)sum[i]

然后f[i]=f[j]+(s-sum[j])*c-sum[j]*c;

其中c就是i到j的长度,s为总节点个数,i为j的父亲,f[i]为以i为集会地点的不方便值。

没错连左儿子右兄弟都不用搞

今天发现了头文件的新写法。。只要一行。。

代码:

#include<bits/stdc++.h>#define g getchar()#define ll long long#define inf 0x3f3f3f3fusing namespace std;inline ll read(){    ll x=0,f=1;char ch=g;    for(;ch<'0'||ch>'9';ch=g)if(ch=='-')f=-1;    for(;ch>='0'&&ch<='9';ch=g)x=x*10+ch-'0';    return x*f;}inline void out(ll x){    int a[25],t=0;    if(x<0)putchar('-'),x=-x;    for(;x;x/=10)a[++t]=x%10;    for(int i=t;i;--i)putchar('0'+a[i]);    if(t==0)putchar('0');    putchar('\n');}ll head[100005],sum[100005],dis[100005],a[100005],s,ans,n,e;struct re{int v,w,next;}ed[200005];inline void ins(int x,int y,int z){    ed[++e]=(re){y,z,head[x]};head[x]=e;}void dp(int x,int f){    for(int i=head[x];i;i=ed[i].next){        if(ed[i].v!=f){            dp(ed[i].v,x);            sum[x]+=sum[ed[i].v];            dis[x]+=dis[ed[i].v]+sum[ed[i].v]*ed[i].w;        }    }    sum[x]+=a[x];}void dp2(int x,int f,int e){    if(x!=1){        dis[x]=(s-sum[x])*e-sum[x]*e+dis[f];        ans=min(dis[x],ans);    }    for(int i=head[x];i;i=ed[i].next){        if(ed[i].v!=f){            dp2(ed[i].v,x,ed[i].w);        }    }}int main(){    n=read();    for(int i=1;i<=n;++i)a[i]=read(),s+=a[i];    for(int i=1;i<n;++i){        int x=read(),y=read(),z=read();        ins(x,y,z);        ins(y,x,z);    }    dp(1,0);    ans=dis[1];    dp2(1,0,0);    out(ans);    return 0;}


0 0