POJ 3140 Contestants Division (树dp)

时间:2023-03-09 07:31:20
POJ 3140 Contestants Division (树dp)

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

题意:

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

思路:

dfs

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1e5 + ;
typedef long long LL;
int n, cnt, head[N];
LL a[N];
struct Edge {
int next, to;
}edge[N << ];
LL dp[N]; inline void add(int u, int v) {
edge[cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt++;
} LL dfs(int u, int p) {
dp[u] = a[u];
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == p)
continue;
dp[u] += dfs(v, u);
}
return dp[u];
} LL f(LL a) {
return a > ? a : -a;
} int main()
{
int m, ca = ;
while(~scanf("%d %d", &n, &m) && (n || m)) {
LL sum = ;
for(int i = ; i <= n; ++i) {
scanf("%lld", a + i);
sum += a[i];
head[i] = -;
}
cnt = ;
int u, v;
while(m--) {
scanf("%d %d", &u, &v);
add(u, v);
add(v, u);
}
dfs(, -);
LL res = sum;
for(int i = ; i <= n; ++i) {
res = min(res, f(sum - *dp[i]));
}
printf("Case %d: %lld\n", ca++, res);
}
return ;
}