1 条题解

  • 0

    题意分析:

    乌拉尔国立大学举办80周年校庆派对,大学的管理结构是一个树状层级,以校长为根节点。派对的出席规则是:如果一个员工出席派对,那么他的直属上司不能出席。每位员工都有一个欢乐值(可能为负数),目标是选择一组员工出席派对,使得在满足上述规则的前提下,所有出席员工的欢乐值总和最大。

    解题思路:

    这个问题可以抽象为树形动态规划(Tree DP)的问题。我们需要在树的结构上进行动态规划,考虑每个节点(员工)是否被选中(出席派对)的情况,同时满足题目给出的约束条件。

    动态规划状态定义

    对于树中的每个节点u,我们可以定义两个状态: dp[u][0]:表示不选择节点u时,以u为根的子树中能获得的最大欢乐值总和。 dp[u][1]:表示选择节点u时,以u为根的子树中能获得的最大欢乐值总和。

    状态转移

    如果选择节点u(即u出席派对),那么u的所有子节点都不能被选择。因此: $dp[u][1] = happy[u] + sum(dp[v][0] for all children v of u)$

    如果不选择节点u(即u不出席派对),那么u的子节点可以选择出席或不出席,我们选择对总和更有利的情况。因此: $dp[u][0] = sum(max(dp[v][0], dp[v][1]) for all children v of u)$

    初始条件

    对于叶子节点(没有子节点的节点): dp[u][0]=0dp[u][0] = 0(不选叶子,子树和为0) dp[u][1]=happy[u]dp[u][1] = happy[u](选叶子,子树和为叶子的欢乐值)

    #include <iostream>
    #include <vector>
    #include <cstdio>
    using namespace std;
    
    const int MAXN = 6005;
    int n;
    int rating[MAXN];
    vector<int> children[MAXN];
    int dp[MAXN][2]; // dp[i][0]表示不选i时的最大欢乐值,dp[i][1]表示选i时的最大欢乐值
    bool hasParent[MAXN];
    
    void dfs(int u) {
        dp[u][0] = 0;
        dp[u][1] = rating[u];
        
        for (int i = 0; i < children[u].size(); i++) {
            int v = children[u][i];
            dfs(v);
            dp[u][0] += max(dp[v][0], dp[v][1]);
            dp[u][1] += dp[v][0];
        }
    }
    
    int main() {
        while (scanf("%d", &n) == 1) {
            // 初始化
            for (int i = 1; i <= n; i++) {
                children[i].clear();
                hasParent[i] = false;
            }
            
            // 读入欢乐值
            for (int i = 1; i <= n; i++) {
                scanf("%d", &rating[i]);
            }
            
            // 读入树结构
            int L, K;
            while (scanf("%d %d", &L, &K) == 2) {
                if (L == 0 && K == 0) break;
                children[K].push_back(L);
                hasParent[L] = true;
            }
            
            // 找到根节点
            int root = 1;
            while (root <= n && hasParent[root]) root++;
            
            // 动态规划计算
            dfs(root);
            
            // 输出结果
            printf("%d\n", max(dp[root][0], dp[root][1]));
        }
        return 0;
    }    
    
    • 1

    信息

    ID
    1343
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    13
    已通过
    1
    上传者