题意:一棵n个结点的带权无根树,从中删去一条边,使得剩下来的两棵子树的节点权值之和的绝对值最小,并求出得到的最小绝对值。
水题,首先把每棵子树的权值之和处理出来,在dfs一次做一下比较就好
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int maxn = 1e5+7;
int n,w[maxn];
LL dp[maxn],ans,sum;
vector<int>q[maxn];
void dfs(int x,int fa)
{
dp[x]=w[x];
for(int i=0;i<q[x].size();i++)
{
int u=q[x][i];if(u==fa) continue;
dfs(u,x);dp[x]+=dp[u];
}
}
void dfss(int x,int fa)
{
for(int i=0;i<q[x].size();i++)
{
int u=q[x][i];if(u==fa) continue;
LL p=sum-2*dp[u];
if(p<0) p=-p;
ans=min(ans,p);
dfss(u,x);
}
}
int main()
{
int i,x,y,m,k=1;
while(scanf("%d%d",&n,&m),m+n)
{
for(i=1;i<=n;i++) q[i].clear();
sum=0;
for(i=1;i<=n;i++) scanf("%d",w+i),sum+=w[i];
ans=sum;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
q[x].push_back(y);
q[y].push_back(x);
}
dfs(1,0);dfss(1,0);
printf("Case %d: %lld\n",k++,ans);
}
return 0;
}