标签:
15
题解:记两个数组dis[](表示根到 i 的距离), size[](表示以 i 根的树的大小),首先dfs一遍,预处理出 1 为根的树(其实可为任意点为根)的总不方便值和dis[], size[], 之后每当改变一个点做根的时候,ans(不方便值)的大小都会: - size[E[i].v] * E[i].v + (tot - size[E[i].v]) * E[i].v (tot 表示 总的牛数),也就是说只有当(2 * size[E[i].v] > tot) 时,ans才会减小。然后就没有然后了。
CODE:
#include <iostream> #include <cstdio> #include <cstring> #define REP(i, s, n) for(int i = s; i <= n; i ++) #define REP_(i, s, n) for(int i = n; i >= s; i --) #define MAX_N 100000 + 10 using namespace std; int n, u, v, w, pel[MAX_N]; long long dis[MAX_N], size[MAX_N]; struct node{ int v, w, next; }E[MAX_N << 1]; int head[MAX_N], top = 0; long long ans = 0, tot = 0; void add(int u, int v, int w){ E[++ top].v = v; E[top].w = w; E[top].next = head[u]; head[u] = top; } void dfs1(int x,int last){ ans += pel[x] * dis[x]; size[x] = pel[x]; for(int i = head[x]; i; i = E[i].next){ if(E[i].v == last) continue; dis[E[i].v] = dis[x] + E[i].w; dfs1(E[i].v, x); size[x] += size[E[i].v]; } } void dfs2(int x,int last){ for(int i = head[x]; i; i = E[i].next){ if(E[i].v == last) continue; if(2 * size[E[i].v] > tot){ ans -= (2 * size[E[i].v] - tot) * E[i].w; dfs2(E[i].v, x); } } } int main(){ scanf("%d", &n); REP(i, 1, n) scanf("%d", &pel[i]), tot += pel[i]; REP(i, 1, n - 1){ scanf("%d%d%d", &u, &v, &w); add(u, v, w); add(v, u, w); } dfs1(1, 0); dfs2(1, 0); cout << ans << endl; return 0; }
标签:
原文地址:http://www.cnblogs.com/ALXPCUN/p/4528083.html