【题目链接】
【算法】
树形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;
}