poj 4045 (树形dp)

题目链接

去年金华邀请赛的B题, 其实就是个挺简单的树上的统计

     

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int N = 50005;
const int M = N << 1;

typedef long long LL;
const LL INF = 1LL << 60;

vector vec;
LL dep[N], sum[N], key[N], son[N];
int head[N], to[M], next[M];
int tot, n, I, R;
LL res;

void init() {
	for (int i = 1; i <= n; i++) {
		head[i] = -1, son[i] = 1, sum[i] = 0;
	}
	tot = 0;
}

void add(int u, int v) {
	to[tot] = v, next[tot] = head[u], head[u] = tot++;
	to[tot] = u, next[tot] = head[v], head[v] = tot++;
}

void dfs(int u, int d, int fa) {
	dep[u] = d;
	for (int i = head[u]; i != -1; i = next[i]) {
		int v = to[i];
		if (v == fa) continue;
		dfs(v, d + 1, u);
		sum[u] += sum[v] + son[v];
		son[u] += son[v];
	}
}

void dfs(int u, int fa) {
	if (fa == 0) {
		key[u] = sum[u];
	}
	else {
		key[u] = key[fa] - 2 * son[u] + n;
	}

	if (key[u] < res) {
		res = key[u];
		vec.clear();
		vec.push_back(u);
	}
	else if (key[u] == res) {
		vec.push_back(u);
	}

	for (int i = head[u]; i != -1; i = next[i]) {
		int v = to[i];
		if (v == fa) continue;
		dfs(v, u);
	}
}

int main() {
	int test, u, v;
	scanf("%d", &test);
	while (test--) {
		scanf("%d%d%d", &n, &I, &R);
		init();
		
		for (int i = 0; i < n - 1; i++) {
			scanf("%d%d", &u, &v);
			add(u, v);
		}
		
		res = INF;
		dfs(1, 0, 0);

		dfs(1, 0);

		sort(vec.begin(), vec.end());

		printf("%lld\n", I * R * I * res);

		for (int i = 0; i < vec.size(); i++)
			printf("%d ", vec[i]);

		printf("\n\n");
	}
	return 0;
}

你可能感兴趣的:(图论)