设uuu是vvv的父亲,dp[u]dp[u]dp[u]是走到uuu的总代价。
设tottottot是总点权,c[u]c[u]c[u]是uuu和它的子树的点权和。
可以发现,集合点从uuu变成vvv的总代价变动为:
1:u1:u1:u和它的子树向vvv走(u,v)−>c[u]∗(u,v)(u,v)->c[u]*(u,v)(u,v)−>c[u]∗(u,v)
2:2:2: 其他的所有节点向uuu走(u,v)−>−(tot−c[u])∗(u,v)(u,v)->-(tot-c[u])*(u,v)(u,v)−>−(tot−c[u])∗(u,v)
dp[v]=dp[u]+c[u]∗(u,v)−(tot−c[u])∗(u,v)dp[v]=dp[u]+c[u]*(u,v)-(tot-c[u])*(u,v)dp[v]=dp[u]+c[u]∗(u,v)−(tot−c[u])∗(u,v)
LonglongLonglongLonglong almostalmostalmost killedkilledkilled me.me.me.
#include<cstdio>
const int MAXN = 1e5 + 10;
int N, cnt = 0;
long long tot = 0;
long long dp[MAXN] = {0};
int c[MAXN], siz[MAXN], h[MAXN];
long long ans = 1000000000000000000;
struct E{
int t, val, nxt;
}Ed[2 * MAXN];
void Dfs(int k, int fa)
{
siz[k] = c[k];
for (int i = h[k]; i; i = Ed[i].nxt)
{
int u = Ed[i].t; if (u == fa) continue;
Dfs(u, k); siz[k] += siz[u];
dp[1] += 1LL * siz[u] * Ed[i].val;
}
}
void Dp(int k, int fa)
{
for (int i = h[k]; i; i = Ed[i].nxt)
{
int u = Ed[i].t; if (u == fa) continue;
dp[u] = dp[k] - 1LL * siz[u] * Ed[i].val + 1LL * (tot - siz[u]) * Ed[i].val;
Dp(u, k);
}
}
void Add(int f, int t, int v) {Ed[++cnt].t = t, Ed[cnt].val = v, Ed[cnt].nxt = h[f], h[f] = cnt;}
long long min(long long a, long long b){return a < b ? a : b;}
int main()
{
scanf("%d", &N);
for (int i = 1; i <= N; i++) scanf("%d", &c[i]), tot += c[i];
for (int i = 1; i < N; i++)
{
int f, t, v; scanf("%d%d%d", &f, &t, &v);
Add(f, t, v), Add(t, f, v);
}
Dfs(1, 0); Dp(1, 0);
for (int i = 1; i <= N; i++) ans = min(ans, dp[i]);
printf("%lld", ans);
return 0;
}