设
u
u
u是
v
v
v的父亲,
d
p
[
u
]
dp[u]
dp[u]是走到
u
u
u的总代价。
设
t
o
t
tot
tot是总点权,
c
[
u
]
c[u]
c[u]是
u
u
u和它的子树的点权和。
可以发现,集合点从
u
u
u变成
v
v
v的总代价变动为:
1
:
u
1:u
1:u和它的子树向
v
v
v走
(
u
,
v
)
−
>
c
[
u
]
∗
(
u
,
v
)
(u,v)->c[u]*(u,v)
(u,v)−>c[u]∗(u,v)
2
:
2:
2: 其他的所有节点向
u
u
u走
(
u
,
v
)
−
>
−
(
t
o
t
−
c
[
u
]
)
∗
(
u
,
v
)
(u,v)->-(tot-c[u])*(u,v)
(u,v)−>−(tot−c[u])∗(u,v)
d
p
[
v
]
=
d
p
[
u
]
+
c
[
u
]
∗
(
u
,
v
)
−
(
t
o
t
−
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)
L o n g l o n g Longlong Longlong a l m o s t almost almost k i l l e d killed killed m e . 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;
}