![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL31kaOdXTE1kMRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5UDNyQzMwQTM4ITOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
本題思路和 這題 是一樣的,
隻不過加了邊權和點權。我們需要再開一個記錄點權的數組, 用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;
}