[洛谷P2986][USACO10MAR]伟大的奶牛聚集Great Cow Gat…

题目大意:给你一棵树,每个点有点权,边有边权,求一个点,使得其他所有点到这个点的距离和最短,输出这个距离

题解:树形$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\n", 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\n", 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\n", ans);
	return 0;
}

  

posted @ 2018-11-02 18:33  Memory_of_winter  阅读(158)  评论(0编辑  收藏  举报