给一个树形结构,每个点又权值,要求把它分成两部分使得两部分权值总和的差距最小。
这里要注意的是,abs好像不能处理64位整形,所以取绝对值函数要手写。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define INF 2000000000
__int64 dp[1000005],first[1000005],next[2000005],num[1000005],sum,min,n;
struct edge
{
__int64 u;
__int64 v;
}en[2000005];
void add(__int64 a,__int64 b,__int64 p)
{
en[p].u=a;
en[p].v=b;
next[p]=first[a];
first[a]=p;
}
void getdp(__int64 s,__int64 f)
{
__int64 i;
for(i=first[s];i!=-1;i=next[i])
{
if(en[i].v!=f)
{
getdp(en[i].v,s);
dp[s]+=dp[en[i].v];
}
}
dp[s]+=num[s];
}
__int64 ju(__int64 a)
{
if(a<0)
return -a;
else
return a;
}
void getmin()
{
__int64 i,j,a;
for(i=2,min=ju(sum-dp[1]-dp[1]);i<=n;i++)
{
a=ju(sum-dp[i]-dp[i]);
if(a<min)
min=a;
}
}
int main()
{
__int64 m,i,j,k,l,a,b,idx,t;
t=0;
while(scanf("%I64d%I64d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
t++;
for(i=1,sum=0;i<=n;i++)
{
scanf("%I64d",&num[i]);
sum+=num[i];
}
idx=0;
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
memset(dp,0,sizeof(dp));
for(i=1;i<=m;i++)
{
scanf("%I64d%I64d",&a,&b);
idx++;
add(a,b,idx);
idx++;
add(b,a,idx);
}
getdp(1,-1);
getmin();
printf("Case %I64d: %I64d\n",t,min);
}
return 0;
}