没有上司的舞会

题目描述

Ural 大学有 N 个职员,编号为 1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

输入格式

第一行一个整数 N。(1<=N<=6000)

接下来 N 行,第 i+1 行表示 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

题解

  • 树形DP,十分明显!
  • 找根节点方法:我们拿cnt[]数组来记录他的上司数目,只有根节点root没有上司,即cnt[root]==0;
  • dp[x][0/1]数组保存x为上司的子树,0和1为选择或不选择时的最大值。由此,状态转移方程显而易见:
dp[root][0]+=max(dp[tmp][1],dp[tmp][0]);
dp[root][1]+=dp[tmp][0];
  • 最后判断并输出最大值,即
cout<<max(dp[i][1],dp[i][0]);

code

#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;
}
posted @ 2020-06-27 16:14  hyskr  阅读(135)  评论(0编辑  收藏  举报