• [洛谷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
    ", 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;
    }
    

      

  • 相关阅读:
    第六周作业
    第五周作业
    2019春第四周作业软件
    2019年春季学期第三周作业
    2019年春季学期第二周作业(文件指针)
    7-2 求最大值及其下标 (20 分)
    7-1 查找整数 (10 分)
    7-1 抓老鼠啊~亏了还是赚了? (20 分)
    秋季学期学习总结
    第6周作业
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9897770.html
Copyright © 2020-2023  润新知