HDU 1520 树形DP入门

HDU 1520

【题目链接】HDU 1520

【题目类型】树形DP

&题意:

某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。

&题解:

poj有一个一样的题,被那个坑了,看的是那个的代码,之后提交hdu总是超时,最后发现递归的时候总是循环n遍,所以才超的时。
只要存下每个节点的孩子就好了,但father数组还是要用的,因为要用它来求根是哪个。(或许也可以不用,但是我没想到)

&代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <algorithm>
#define cle(a,v) memset(a,(v),sizeof(a))
#define ll long long
const int maxn = 6000 + 7;
int n, dp[maxn][2], father[maxn], u, v;
bool vis[maxn];
std::vector<int> ch[maxn];
void tree_dp(int u) {
	vis[u] = 1;
	for (int i = 0; i < ch[u].size(); i++) {
		if (!vis[ch[u][i]] && father[ch[u][i]] == u) {
			tree_dp(ch[u][i]);
			dp[u][1] += dp[ch[u][i]][0];
			dp[u][0] += std::max(dp[ch[u][i]][1], dp[ch[u][i]][0]);
		}
	}
}
int main() {
	freopen("1.in", "r", stdin);
	while (~scanf("%d", &n)) {
		for (int i = 1; i <= n; i++)
			ch[i].clear();
		memset(father, -1, sizeof(father));
		memset(vis, 0, sizeof(vis));
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++) {
			scanf("%d", &dp[i][1]);
		}
		int root = 1;
		while (scanf("%d%d", &u, &v), u || v) {
			father[u] = v;
			ch[v].push_back(u);
		}
		while (father[root] != -1) root = father[root];
		// printf("%d
", root);
		tree_dp(root);
		printf("%d
", std::max(dp[root][1], dp[root][0]));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/s1124yy/p/7259767.html