【POJ 3140】 Contestants Division

【题目链接】

              点击打开链接

【算法】

           树形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;
}

猜你喜欢

转载自blog.csdn.net/even_bao/article/details/80329333
今日推荐