→题目链接←
【想说的话】
没有什么想说的=.=
周末没什么事不刷题感觉不太好
【题解】
两遍dfs(树形dp)
将点1当作根
第一遍dfs计算出每个点子节点总数,还有将它作为集会地点时它的子树中的点满足条件需要的代价
第二遍计算出答案,点1的答案就是dfs1时处理出的代价,剩下的点的答案就对于它与它父亲节点的那条边计算一下就好
具体看代码吧
【代码】
#include<bits/stdc++.h>
#define MAXN 100010
#define ll long long
#define inf 1000000000
using namespace std;
inline int rd(){
int x=0,y=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')y=-y;c=getchar();}
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x*y;
}
struct node{
int to,len;
node(int x,int y){to=x,len=y;}
};
int n;
vector<node>v[MAXN];
int a[MAXN],fa[MAXN];
ll ans[MAXN],sum[MAXN],num[MAXN];
ll tot=0;
inline void link(int x,int y,int z){
v[x].push_back(node(y,z));
v[y].push_back(node(x,z));
}
void dfs1(int x){
num[x]=a[x];
sum[x]=0;
for(int i=0; i<v[x].size(); i++){
int to=v[x][i].to;
int len=v[x][i].len;
if(to==fa[x])continue;
fa[to]=x;
dfs1(to);
num[x]+=num[to];
sum[x]+=sum[to]+num[to]*len;
}
}
void dfs2(int x,int len){
if(!fa[x])ans[x]=sum[x];
else ans[x]=ans[fa[x]]-num[x]*len+(tot-num[x])*len;
for(int i=0; i<v[x].size(); i++){
int to=v[x][i].to;
int len=v[x][i].len;
if(fa[x]==to)continue;
dfs2(to,len);
}
}
int main(){
memset(fa,0,sizeof(fa));
n=rd();
for(int i=1; i<=n; i++)a[i]=rd(),tot+=a[i];
for(int i=1; i<n; i++){
int x=rd(),y=rd(),z=rd();
link(x,y,z);
}
dfs1(1);
dfs2(1,0);
ll Min=(ll)inf*(ll)inf;
for(int i=1; i<=n; i++)Min=min(Min,ans[i]);
printf("%lld\n",Min);
return 0;
}