Gold
先预处理出在节点1建立集会的值,然后通过运算向儿子节点转移
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 200003 #define ll long long using namespace std; ll n,m; ll point[N],next[N],u[N],v[N],c[N],tot,size[N],len[N],sum; ll cost[N],f[N]; void add(ll x,ll y,ll z) { tot++; next[tot]=point[x]; point[x]=tot; u[tot]=y; v[tot]=z; tot++; next[tot]=point[y]; point[y]=tot; u[tot]=x; v[tot]=z; } void dfs(ll x,ll fa) { for (ll i=point[x];i;i=next[i]) if (u[i]!=fa) { len[u[i]]=len[x]+v[i]; dfs(u[i],x); cost[x]+=cost[u[i]]; size[x]+=size[u[i]]; } size[x]+=len[x]*c[x]; cost[x]+=c[x]; } void solve(ll x,ll fa) { for (ll i=point[x];i;i=next[i]) if (u[i]!=fa) { f[u[i]]=f[x]+(sum-cost[u[i]])*v[i]-cost[u[i]]*v[i]; solve(u[i],x); } } int main() { freopen("a.in","r",stdin); scanf("%lld",&n); for (ll i=1;i<=n;i++) scanf("%lld",&c[i]),sum+=c[i]; for (ll i=1;i<n;i++) { ll x,y,z; scanf("%lld%lld%lld",&x,&y,&z); add(x,y,z); } dfs(1,0); f[1]=size[1]; solve(1,0); ll ans=1e16; for (ll i=1;i<=n;i++) ans=min(ans,f[i]); printf("%lld\n",ans); }