本题思路和 这题 是一样的,
只不过加了边权和点权。我们需要再开一个记录点权的数组, 用sum记录点权总和
换根过程:dp[child=dp[rt]+w*(sum-2*size[child]) w为rt 、child的边权,size[i]表示以i为根的树的总点权。
//#pragma comment(linker, "/STACK:102400000,102400000")//手动扩栈
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<math.h>
#include<set>
#include<unordered_map>
using namespace std;
#define LL long long
#define ULL unsigned long long
const int INF=0x3f3f3f3f;
const double eps=1e-5;
const int maxn=1e5+7;
struct
{
int to,next,w;
}edge[maxn<<1];
int head[maxn],cnt=1;
void add(int from,int to,int w)
{
edge[cnt].w=w;
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt++;
}
int num[maxn];//每个顶点的奶牛数
int n;
LL size[maxn];//以i为顶点的子树 奶牛总数
LL dep[maxn];
LL dp[maxn];
LL sum;
void dfs(int rt,int par,int d)
{
dep[rt]=d;
size[rt]=num[rt];
for(int i=head[rt];i;i=edge[i].next)
{
int to=edge[i].to;
if(to==par) continue;
dfs(to,rt,d+edge[i].w);
size[rt]+=size[to];
}
}
void DFS(int rt,int par)
{
for(int i=head[rt];i;i=edge[i].next)
{
int to=edge[i].to;
if(to==par) continue;
dp[to]=dp[rt]+edge[i].w*(sum-2*size[to]);
DFS(to,rt);
}
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",num+i);
sum+=num[i];
}
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
dfs(1,1,0);
for(int i=2;i<=n;i++)
{
dp[1]+=dep[i]*num[i];
}
DFS(1,1);
LL mmin=dp[1];
for(int i=2;i<=n;i++) mmin=min(mmin,dp[i]);
cout<<mmin;
system("pause");
return 0;
}