题意:
给一棵树,每个节点有一个值v,现在要去掉一条边,使分成的两棵树的v的和的差值最小。
分析:
水题,注意数据范围。
代码:
//poj 3140
//sep9
#include <iostream>
using namespace std;
const int maxN=200024;
int n,m,e;
__int64 sum,ans;
struct Edge
{
int v,next;
}edge[maxN];
__int64 v[maxN];
int head[maxN];
__int64 dfs(int p,int u)
{
__int64 tmp=v[u];
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v!=p){
__int64 t=dfs(u,v);
ans=min(ans,max(t,sum-t)-min(t,sum-t));
tmp+=t;
}
}
return tmp;
}
int main()
{
int cases=0;
while(scanf("%d%d",&n,&m)==2&&n){
e=0,sum=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;++i){
scanf("%I64d",&v[i]);
sum+=v[i];
}
while(m--){
int a,b;
scanf("%d%d",&a,&b);
edge[e].v=b;edge[e].next=head[a];head[a]=e++;
edge[e].v=a;edge[e].next=head[b];head[b]=e++;
}
ans=sum;
dfs(-1,1);
printf("Case %d: %I64d\n",++cases,ans);
}
return 0;
}