首页 > 代码库 > POJ2342Anniversary party(树形dp)
POJ2342Anniversary party(树形dp)
POJ2342Anniversary party(树形dp)
题目连接
题目大意:有一个聚会,现在需要邀请人来参加这个聚会来增加活跃度,但是这N个人中,除了一个人以外,其余的人都有直接的上司,如果他们碰到他们的直接的上司的话,那么他们就会很不愉快。现在要求你让所有的人都愉快的情况下,使得聚会的活跃度,达到最大。
解题思路:之前没有接触过树形dp,看了题解大概明白。题型大概就是N个节点形成了一棵树,根节点需要用到子节点的数据。思路:先把每个点的直接的子节点找出来,存在vector里面。然后找出根节点,最后再dfs从根找到子节点,然后数据再一层一层的返回。
dp[i][0] 代表i这个节点不选 dp[i][1] 代表i这个节点选择了
dp[i][0] += max (dp[子节点][0], dp[子节点][1]);//上层节点不选了,那么子节点可选可不选
dp[i][1] += max(dp[子节点][0] + score[i], dp[i][1]); //上层节点选了,那么子节点都是不可选的
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int maxn = 6005;
int dp[maxn][2], vis[maxn];
int score[maxn];
vector<int> node[maxn];
int f[maxn];
void tree_dp (int num) {
vis[num] = 1;
dp[num][0] = 0;
dp[num][1] = score[num];
//printf ("%d %d\n", num, node[num].size());
for (int i = 0; i < node[num].size(); i++) {
int u = node[num][i];
if (vis[u])
continue;
tree_dp(u);
dp[num][0] += max(dp[u][1], dp[u][0]);
dp[num][1] += dp[u][0];
}
}
void init () {
for (int i = 0; i < n; i++)
scanf ("%d", &score[i]);
for (int i = 0; i < n; i++)
node[i].clear();
memset (vis, 0, sizeof (vis));
memset (f, -1, sizeof(f));
while (scanf ("%d%d", &a, &b) && (a||b) ){
node[b - 1].push_back(a - 1);
f[a - 1] = b - 1;
}
}
int main () {
int n, a, b;
while (scanf ("%d", &n) != EOF) {
init();
for (int i = 0; i < n; i++){
if (f[i] == -1) {
tree_dp(i);
printf ("%d\n", max(dp[i][0], dp[i][1]));
break;
}
}
}
return 0;
}
POJ2342Anniversary party(树形dp)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。