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
", 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;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6432933.html