树形dp,水。 求将一棵节点有权值的树分成两块,两块总权值差最小值。
ps:注意本题要用longlong,第一次应该wa在这里,然后换了种写法,导致tot和mv未初始化,再wa一发。还是将tot和mv的初始化放进init中好,这类题目初始化问题需要格外注意,不能忘了调用init。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
#define INF 100000000000007
#define N 200005
int n, m;
struct Node{
int v;
Node *next;
}e[N], *head[N];
LL sum[N], peo[N];
int ptr = 0;
LL mv;
LL tot;
void init(){
ptr = 0;
mv = INF;
tot = 0;
for(int i = 0; i <= n; i++){
head[i] = NULL;
sum[i] = 0;
peo[i] = 0;
}
}
void adde(int x, int y){
e[ptr].v = x;
e[ptr].next = head[y];
head[y] = &e[ptr ++];
e[ptr].v = y;
e[ptr].next = head[x];
head[x] = &e[ptr ++];
}
LL tdp(int x, int par){
Node *p = head[x];
sum[x] += peo[x];
while(p){
if(p -> v != par){
LL vv = tdp(p -> v, x);
sum[x] += vv;
}
p = p -> next;
}
return sum[x];
}
int main(){
int num = 1;
while(scanf("%d%d", &n, &m) , n || m){
init();
for(int i = 1; i <= n; i++){
scanf("%d", &peo[i]);
tot += peo[i];
}
int x, y;
for(int i = 0; i < m; i++){
scanf("%d%d", &x, &y);
adde(x, y);
}
tdp(1, 0);
for(int i = 1; i <= n; i++){
LL vv = tot - sum[i] * 2;
if(vv < 0) vv = - vv;
if(vv < mv)mv = vv;
}
printf("Case %d: ", num++);
printf("%I64d\n", mv);
}
return 0;
}