一棵树的节点上均有权值, 将这棵树切成两半, 两个part之间的权值之和差异最小
记忆化搜索
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define LL long long
using namespace std;
const int MAXN = 1e5+10;
const int MAXM = 1e6+10;
int n,m;
LL val[MAXN];
struct Edge{
int to,next;
Edge(){}
Edge(int a,int b){
to = a,next = b;
}
}edge[MAXM];
LL dp[MAXN];
int head[MAXN],top;
LL ans,sum;
LL aabs(LL a){
return a<0?-a:a;
}
void init(){
memset(head,-1,sizeof(head));
top = 0,sum = 0;
memset(dp,-1,sizeof(dp));
ans = -1;
}
void add(int u,int v){
edge[top] = {v,head[u]};
head[u] = top++;
}
LL DFS(int u,int fa){
if(dp[u] != -1){
return dp[u];
}
LL temp = val[u];
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == fa) continue;
temp += DFS(v,u);
}
LL a = aabs(sum-(LL)2*temp);
if(ans == -1 || a<ans){
ans = a;
}
return dp[u] = temp;
}
int main(){
int u,v;
int t = 0;
while(scanf("%d%d",&n,&m),n||m){
init();
for(int i = 1; i <= n; ++i){
scanf("%lld",&val[i]);
sum += val[i];
}
while(m--){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
DFS(1,-1);
printf("Case %d: %lld\n",++t,ans);
}
return 0;
}