POJ 3140 Contestants Division (树dp)

题目链接:http://poj.org/problem?id=3140

题意:

        给你一棵树,问你删去一条边,形成的两棵子树的节点权值之差最小是多少。

思路:

        dfs

复制代码
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 1e5 + 5;
 7 typedef long long LL;
 8 int n, cnt, head[N];
 9 LL a[N];
10 struct Edge {
11     int next, to;
12 }edge[N << 1];
13 LL dp[N];
14 
15 inline void add(int u, int v) {
16     edge[cnt].next = head[u];
17     edge[cnt].to = v;
18     head[u] = cnt++;
19 }
20 
21 LL dfs(int u, int p) {
22     dp[u] = a[u];
23     for(int i = head[u]; ~i; i = edge[i].next) {
24         int v = edge[i].to;
25         if(v == p)
26             continue;
27         dp[u] += dfs(v, u);
28     }
29     return dp[u];
30 }
31 
32 LL f(LL a) {
33     return a > 0 ? a : -a;
34 }
35 
36 int main()
37 {
38     int m, ca = 1;
39     while(~scanf("%d %d", &n, &m) && (n || m)) {
40         LL sum = 0;
41         for(int i = 1; i <= n; ++i) {
42             scanf("%lld", a + i);
43             sum += a[i];
44             head[i] = -1;
45         }
46         cnt = 0;
47         int u, v;
48         while(m--) {
49             scanf("%d %d", &u, &v);
50             add(u, v);
51             add(v, u);
52         }
53         dfs(1, -1);
54         LL res = sum;
55         for(int i = 1; i <= n; ++i) {
56             res = min(res, f(sum - 2*dp[i]));
57         }
58         printf("Case %d: %lld\n", ca++, res);
59     }
60     return 0;
61 }
复制代码

 

posted @   Recoder  阅读(195)  评论(0编辑  收藏  举报
编辑推荐:
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
阅读排行:
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 用99元买的服务器搭一套CI/CD系统
· Excel百万数据如何快速导入?
· ShadowSql之.net sql拼写神器
点击右上角即可分享
微信分享提示