https://www.luogu.org/problem/show?pid=2986
就是树形dp;
主要思路就是我们算出假如全到第一个点的情况的答案;
那么我们再通过第一个点再往下移动,移动一个算一个;
就好啦
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const Ll N=1e5+5;
struct cs{Ll to,nxt,l;}a[N*2];
Ll head[N],ll;
//v是这个子树所有的节点到这个点的距离和
//c就是子树所有节点数量
Ll v[N],ans[N],c[N];
Ll n,m,x,y,z,Ans=1e18;
void init(Ll x,Ll y,Ll z){
a[++ll].l=z;
a[ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void DFS(Ll x,Ll y){
for(Ll k=head[x];k;k=a[k].nxt)
if(a[k].to!=y){
DFS(a[k].to,x);
v[x]+=v[a[k].to]+c[a[k].to]*a[k].l;
c[x]+=c[a[k].to];
}
}
void dfs(Ll x,Ll y,Ll l){
if(!y)Ans=min(ans[x]=v[x],Ans);else
Ans=min(ans[x]=ans[y]+l*(c[1]-c[x]*2),Ans);
for(Ll k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs(a[k].to,x,a[k].l);
}
int main()
{
scanf("%lld",&n);
for(Ll i=1;i<=n;i++)scanf("%lld",&c[i]);
for(Ll i=1;i<n;i++){
scanf("%lld%lld%lld",&x,&y,&z);
init(x,y,z);init(y,x,z);
}
DFS(1,0);
dfs(1,0,0);
printf("%lld",Ans);
}