HDU 1520 树形DP入门

时间:2021-04-14 08:19:57

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\n", root);
tree_dp(root);
printf("%d\n", std::max(dp[root][1], dp[root][0]));
}
return 0;
}