• 猴腮雷


    猴腮雷

    题目描述

    • 新年就要来临啦,小猴腮雷一家 N 人将作为嘉宾被邀请到了春晚上。然而小猴腮雷的一家都曾经是大名鼎鼎的熊孩子,无论在什么时候都会,也只会和自己的直系亲属,也就是父母吵架,当然,即便是在春晚这个舞台上也是这样。
    • 为了到时候不会引起战争,组委会据此思考到底要邀请哪些人?更让组委会头疼是,每个猴腮雷拥有一个活泼值 A_i ,组委会既想要他们不会发生矛盾,也想尽量让来参加的猴腮雷活泼值的和最大.

    输入格式

    • 第一行一个整数 N
    • 接下来 N 行,第 i+1 行表示 i 号猴腮雷的活泼值 A_i
    • 接下来 N-1 行,每行输入一对整数 L,K 。表示 K L 是直接亲属关系。
    • 最后一行输入 0,0

    输出格式

    一行整数表示最大的活泼值的和。

    样例

    样例输入

    7 
    1 
    1 
    1 
    1 
    1 
    1 
    1 
    1 3 
    2 3 
    6 4 
    7 4 
    4 5 
    3 5 
    0 0
    

    样例输出

    5
    

    数据范围与提示

    • 对于 70\% 的数据 1=<N<=1000
    • 对于 100\% 的数据 1<=N<=6000, -128<=A_i<=127

    题解

    • 裸的树型 dp,和 没有上司的舞会 完全相同。
    • 我们只需定义 dp[i][0/1] :表示以 i 为根的子树,不选/选 i 的最大活跃度。
      • dp[i][0]=sonimax(dp[son][0],dp[son][1])
      • dp[i][1]=sonidp[i][0]

    code1

    using namespace std;
    const int maxn = 6010;
    struct Edge {
        int next, to;
    } edge[maxn];
    int head[maxn], dp[maxn][3], a[maxn], n;
    int tot = 0;
    void add(int x, int y) {
        edge[++tot].to = y;
        edge[tot].next = head[x];
        head[x] = tot;
    }
    void tree_dp(int root) {
        dp[root][0] = 0;
        dp[root][1] = a[root];
        for (int x = head[root]; x; x = edge[x].next) {
            tree_dp(edge[x].to);
            dp[root][0] += max(dp[edge[x].to][0], dp[edge[x].to][1]);
            dp[root][1] += dp[edge[x].to][0];
        }
    }
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        int root = 1;
        for (int i = 1; i < n; i++) {
            int x, y;
            cin >> x >> y;
            if (root == x)
                root = y;
            add(y, x);
        }
        int x, y;
        cin >> x >> y;
        tree_dp(root);
        cout << max(dp[root][0], dp[root][1]);
        return 0;
    }
    

    code2

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 6500;
    const int Inf = 0x3f3f3f3f;
    int dp[maxn][maxn], jl[maxn];
    int map_[maxn][maxn];
    int r[maxn], tot[maxn], cnt[maxn];
    int tmp, ans;
    
    void tree_dp(int root) {
        for (int i = 0; i < tot[root]; i++) {
            int tmp = map_[root][i];
            tree_dp(tmp);
            dp[root][0] += max(dp[tmp][1], dp[tmp][0]);
            dp[root][1] += dp[tmp][0];
        }
        dp[root][1] += r[root];
    }
    int main() {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> r[i];
        }
        int l, k;
        for (int i = 1; i <= n; i++) {
            cin >> l >> k;
            map_[k][tot[k]++] = l;
            cnt[l]++;
        }
        for (int i = 1; i <= n; i++)
            if (cnt[i] == 0) {
                tree_dp(i);
                cout << max(dp[i][1], dp[i][0]);
                return 0;
            }
        return 0;
    }
    
  • 相关阅读:
    Trie树与AC自动机
    学习强国答题小程序
    小程序如何引导添加个人微信号
    成语答题赚小程序里面涉及到金额的小数计算问题
    答题小程序v2.0
    活动抽奖小程序
    抽奖小程序分享
    抽奖小程序结果页设计
    抽奖小程序数据库设计
    答题活动小程序复盘记录
  • 原文地址:https://www.cnblogs.com/hellohhy/p/13226643.html
Copyright © 2020-2023  润新知