• 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
  • 相关阅读:
    PHP获取时间or戳?
    滤镜灰CSS
    css3 文字渐变色
    除指定区域外点击任何地方隐藏DIV
    margin-top bug 处理方案
    基于Bootstrap好用的瀑布流
    初始数据库
    协程
    粘包及解决方案
    log日志的三种方式
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6432933.html
Copyright © 2020-2023  润新知