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