【题目链接】

              点击打开链接

【算法】

           树形DP

           ans = min{ | total - 2 * sum[k] | } (sum为以k为根的子树的权值和)

  【代码】

            

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXN 1000010
const long long INF = 1e13;

long long i,x,y,n,m,tot,ans,TC;
vector<long long> e[MAXN];
long long sum[MAXN],val[MAXN];

inline long long abs(long long x) { return x < 0 ? -x : x; }
inline void dfs(long long x,long long fa)
{
    long long i,y;
    sum[x] = val[x];
    for (i = 0; i < e[x].size(); i++)
    {
        y = e[x][i];
        if (fa == y) continue;
        dfs(y,x);
        sum[x] += sum[y];    
    }    
    if (abs(tot-sum[x]*2) < ans) ans = abs(tot-sum[x]*2); 
}

int main()
{
    
    while (scanf("%lld%lld",&n,&m) != EOF)
    {
        tot = 0;
        ans = INF;
        if (!n && !m) break;
        for (i = 1; i <= n; i++) e[i].clear();
        for (i = 1; i <= n; i++) 
        {
            scanf("%lld",&val[i]);
            tot += val[i];
        }    
        for (i = 1; i <= m; i++)
        {
            scanf("%lld%lld",&x,&y);
            e[x].push_back(y);
            e[y].push_back(x);    
        }    
        dfs(1,0);
        printf("Case %lld: %lld\n",++TC,ans);
    }
    
    return 0;
}