【题目大意】:给出一棵树,每个节点都有一个权值。删除一条边之后,问两棵子树的权值之差的最少为多少。
【解题思路】:利用dfs枚举边,记忆化搜索记录下到达当前节点并以当前节点为根的子树的权值,记为dp[i];
则我们可以得出,两棵子树的权值之差就是abs(sum-dp[i]-dp[i])....对于每一个点去min就是答案了。
【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define linf 1LL<<60
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
int n,m;
ll v[100100],dp[100100],summ,ans;
vector<int> way[100100];
ll ABS(ll a){
if (a>0) return a;
else return -a;
}
void solve_dfs(int u,int fr){
int vv;
dp[u]=v[u];
for (int i=0; i<way[u].size(); i++){
vv=way[u][i];
if (vv!=fr){
solve_dfs(vv,u);
dp[u]+=dp[vv];
ans=min(ABS(summ-2*dp[vv]),ans);
}
}
return ;
}
int main() {
int cas=1;
while (~scanf("%d%d",&n,&m)){
if (n==0 && m==0) break;
for (int i=0; i<100100; i++)
way[i].clear();
ans=linf;
summ=0;
for (int i=1; i<=n; i++){
scanf("%lld",&v[i]);
summ+=v[i];
}
int u,v;
for (int i=0; i<m; i++){
scanf("%d%d",&u,&v);
way[u].pb(v);
way[v].pb(u);
}
solve_dfs(1,-1);
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}