Description
Given a large tree nodes bit right, while the right side there is obtained a point ANS, so that the minimum cost, wherein $ cost = \ sum \ limits_ {i = 1} ^ {n} {val [i] * dis (ans, i)} $
Solution
Tree dp
Still resolved through twice dfs
The core idea is "second to scan and change root Act" (the term comes from lyd "algorithm contest Step-up Guide")
We assume that dfs is the root and the first pass is determined ans when positioned at the expense of a DIS
There is clearly $ dis [i] = \ sum \ limits_ {j \ in son (i)} {dis [j] + len (i, j) * tot [j]} $, wherein TOT [j] represents a j is a right subtree rooted at a node point, and
So we dfs then again to achieve "change root"
Suppose the current node i, and i father had calculated correctly, we remember the price ans located at his father as $ f [fa] $, we consider how by $ f [fa] $ find $ f [i] $
$ F [fa] $ comprising two parts: i consideration in the subtree rooted and the rest. So we first $ f [fa] $ i is minus the cost of sub-tree root, and then add the subtree rooted at i went i costs, plus the cost of the remainder of the i's to come
See detailed implementation code.
Time complexity is $ O (n) $
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 100010; 5 inline int read() { 6 int ret = 0, op = 1; 7 char c = getchar(); 8 while (!isdigit(c)) { 9 if (c == '-') op = -1; 10 c = getchar(); 11 } 12 while (isdigit(c)) { 13 ret = ret * 10 + c - '0'; 14 c = getchar(); 15 } 16 return ret * op; 17 } 18 struct node { 19 int nxt, to, dis; 20 } a[maxn << 1]; 21 int num, head[maxn], n, val[maxn]; 22 ll tot[maxn], dis[maxn], f[maxn]; 23 ll sum; 24 inline void add(int from, int to, int dis) { 25 a[++num].nxt = head[from]; 26 a[num].to = to; 27 a[num].dis = dis; 28 head[from] = num; 29 } 30 ll dfs(int now, int fa) { 31 for (register int i = head[now]; i; i = a[i].nxt) { 32 int to = a[i].to; 33 if (to == fa) continue ; 34 ll ret = dfs(to, now); 35 dis[now] += dis[to] + a[i].dis * ret; 36 tot[now] += ret; 37 } 38 return tot[now] = tot[now] + val[now]; 39 } 40 void dp(int now, int fa) { 41 for (register int i = head[now]; i; i = a[i].nxt) { 42 int to = a[i].to; 43 if (to == fa) continue ; 44 f[to] = (f[now] - (dis[to] + a[i].dis * tot[to])) + (a[i].dis * (sum - tot[to])) + dis[to]; 45 dp(to, now); 46 } 47 } 48 int main() { 49 n = read(); 50 for (register int i = 1; i <= n; ++i) val[i] = read(), sum += val[i]; 51 for (register int i = 1; i < n; ++i) { 52 int x = read(), y = read(), z = read(); 53 add(x, y, z); add(y, x, z); 54 } 55 dfs(1, 1); 56 f[1] = dis[1]; 57 dp(1, 1); 58 ll ans = 9223372036854775806ll; 59 for (register int i = 1; i <= n; ++i) ans = min(ans, f[i]); 60 printf("%lld\n", ans); 61 return 0; 62 }