POJ 2342 Anniversary party 树形dp入门

http://poj.org/problem?id=2342

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

对于每一个人,都有两种情况,选,或者不选。然后选了后,他的下属就只能不选了,如果它不选,下属可能选或者不选。

这样用dfs + 记忆化搜索,就好了

每次搜索,就是要求以第cur个节点为根的子树中,其中第cur个节点的状态是sel(选或者不选)时的最大值。

记忆化搜索可以开两个数组来,一个用DFN优化,也就是时间轴,就不需要memset了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
int n;
const int maxn = 6000 + 20;
struct node {
    int u, v, w, tonext;
}e[maxn * 2];
int num;
int first[maxn];
int val[maxn];
int in[maxn], DFN;
int vis[maxn][2], dp[maxn][2];
void add(int u, int v) {
    ++num;
    e[num].u = u;
    e[num].v = v;
    e[num].tonext = first[u];
    first[u] = num;
}
int dfs(int cur, bool sel) {
    if (vis[cur][sel] == DFN) {
        return dp[cur][sel];
    }
    vis[cur][sel] = DFN;
    if (sel) {
        int ans = 0;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            ans += dfs(v, false);
        }
        dp[cur][sel] = val[cur] + ans;
        return val[cur] + ans;
    } else {
        int ans = 0;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            ans += max(dfs(v, true), dfs(v, false));
        }
        dp[cur][sel] = ans;
        return ans;
    }
}
void work() {
    num = 0;
    memset(first, 0, sizeof first);
    ++DFN;
    for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);
    for (int i = 1; i <= n - 1; ++i) {
        int u, v;
        scanf("%d%d", &v, &u);
        add(u, v);
        in[v] = DFN;
    }
    int root = -inf;
    for (int i = 1; i <= n; ++i) {
        if (in[i] != DFN) {
            root = i;
            break;
        }
    }
    printf("%d\n", max(dfs(root, false), dfs(root, true)));
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    while (scanf("%d", &n) != EOF && n) work();
    return 0;
}

时间: 2024-10-12 15:51:08

POJ 2342 Anniversary party 树形dp入门的相关文章

POJ 2342 Anniversary party (树形dp 入门题)

Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4810   Accepted: 2724 Description There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure

POJ 2342 Anniversary party 树形DP基础题

题目链接:http://poj.org/problem?id=2342 题目大意:在一个公司中,每个职员有一个快乐值ai,现在要开一个party,邀请了一个员工就不可能邀请其直属上司,同理邀请了一个人就不可以邀请其的直属员工, 问如何使得这个快乐值达到最大. 题解:对每个结点dp[i][0]表示不邀请这个员工,其子树达到的最大快乐值,dp[i][1]表示邀请i员工其子树达到的最大值. dp[i][0]=(i的全部员工的max(dp[u][1],dp[u][0)相加,也就是其子员工来或不来的最大快

POJ 2342 Anniversary Party ( 树形DP )

deque 的插入操作不一定有 vector 快 #include <iostream> #include <cstring> #include <fstream> #include <vector> using namespace std; #define NOT_SELECTED 0 #define SELECTED 1 #define SIZE 6001 vector< int > relations[SIZE]; bool visited

poj 2324 Anniversary party(树形DP)

/*poj 2324 Anniversary party(树形DP) ---用dp[i][1]表示以i为根的子树节点i要去的最大欢乐值,用dp[i][0]表示以i为根节点的子树i不去时的最大欢乐值, ---于是当i去时,i的所有儿子都不能去:dp[i][1]=sum(dp[j][0])+a[i],其中j是i的儿子节点. ---当i不去时,i的儿子可去也可不去:dp[i][0]=sum(max(dp[j][0],dp[j][1])),j是i的儿子节点 ---边界条件:当i时叶子节点时,dp[i][

[poj2342]Anniversary party树形dp入门

题意:选出不含直接上下司关系的最大价值. 解题关键:树形dp入门题,注意怎么找出根节点,运用了并查集的思想. 转移方程:dp[i][1]+=dp[j][0];/i是j的子树 dp[i][0]+=max(dp[j][0],dp[j][1]); 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<iostream> 6

POJ 2342 Anniversary party (树dp)

题目链接:http://poj.org/problem?id=2342 有n个人,每个人有活跃值.下面n-1行u和v表示u的上司是v,有直接上司和下属的关系不能同时参加party,问你party最大的活跃值是多少. 也就是说一棵树中,选择的点不能是相邻的点,且要使活跃值最大. 简单的树形dp,任意选一个点开始遍历,从叶子节点开始回溯. dp[i][0]表示不选i节点最大的活跃度,则dp[i][1]表示选i节点最大的活跃度. i与j相连,dp[i][0] += max(dp[j][0], dp[j

hdu oj 1520 Anniversary party(树形dp入门)

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6990    Accepted Submission(s): 3104 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

Anniversary party(树形DP入门)

Anniversary party HDU - 1520 There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted at the rect

poj 2342 &amp;&amp; hdu 1520 树形dp

题意:有n个人,接下来n行是n个人的价值,再接下来n行给出l,k说的是l的上司是k,这里注意l与k是不能同时出现的 链接:点我 dp[i][1] += dp[j][0], dp[i][0] += max{dp[j][0],dp[j][1]};其中j为i的孩子节点. 第二次做感觉已经很水了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #i