猴腮雷

猴腮雷

题目描述

  • 新年就要来临啦,小猴腮雷一家 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;
}
原文地址:https://www.cnblogs.com/hellohhy/p/13226643.html