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 }