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 @ 2016-10-11 14:52  Recoder  阅读(193)  评论(0编辑  收藏  举报