题目大意:给你一棵树,每个点有点权,边有边权,求一个点,使得其他所有点到这个点的距离和最短,输出这个距离
题解:树形$DP$,思路清晰,转移显然
卡点:无
C++ Code:
#include <cstdio> #include <algorithm> #define maxn 100010 const long long inf = 0x3f3f3f3f3f3f3f3f; int head[maxn], cnt; struct Edge { int to, nxt, w; } e[maxn << 1]; inline void add(int a, int b, int c) { e[++cnt] = (Edge) {b, head[a], c}; head[a] = cnt; } int n, sum; int w[maxn], sz[maxn]; long long f[maxn], ans; void dfs(int u, int fa = 0) { sz[u] = w[u]; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa) { dfs(v, u); sz[u] += sz[v]; f[u] += f[v] + static_cast<long long> (sz[v]) * e[i].w; } } } void dfs1(int u, int fa = 0) { ans = std::min(ans, f[u]); // printf("%d: %lld ", u, f[u]); for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa) { f[v] = f[u] - static_cast<long long> (sz[v]) * e[i].w + static_cast<long long> (sum - sz[v]) * e[i].w; // printf("%d -> %d : %d %d %lld %lld ", u, v, sz[v], e[i].w, f[u], f[v]); dfs1(v, u); } } } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", w + i), sum += w[i]; for (int i = 1, a, b, c; i < n; i++) { scanf("%d%d%d", &a, &b, &c); add(a, b, c); add(b, a, c); } dfs(1); ans = f[1]; __builtin_memset(f, 0, sizeof f); f[1] = ans; dfs1(1); printf("%lld ", ans); return 0; }