P1352 没有上司的舞会

解题思路

这是一道经典的树形动态规划问题。我们需要在一棵树中选择一些节点(职员),使得:

  1. 不能同时选择一个节点和它的直接父节点(上司和下属不能同时参加)

  2. 选择的节点的权值(快乐指数)之和最大

动态规划的状态设计:

  • dp[u][0] 表示不选择节点 u 时,以 u 为根的子树能获得的最大快乐值

  • dp[u][1] 表示选择节点 u 时,以 u 为根的子树能获得的最大快乐值

状态转移方程:

  1. 当不选择 u 时,它的子节点可以选择或不选择:
    dp[u][0] = Σ max(dp[v][0], dp[v][1]) (v 是 u 的子节点)

  2. 当选择 u 时,它的子节点不能被选择:
    dp[u][1] = a[u] + Σ dp[v][0] (v 是 u 的子节点)

最终结果是 max(dp[root][0], dp[root][1])

代码注释

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10, inf = 0x3f3f3f3f;
vector<int> g[N];  // 邻接表存储树结构
int f[N];          // 记录每个节点的父节点
int a[N];          // 存储每个节点的快乐指数
int dp[N][2];      // dp数组,dp[u][0]表示不选u时的最大值,dp[u][1]表示选u时的最大值
int n, rt, ans = -1e9;  // n是节点数,rt是根节点,ans存储最终答案

void dfs(int x) {
    dp[x][1] = a[x];  // 初始化:选择x时的快乐值至少是x本身的快乐值
    int sum1 = 0, sum2 = 0;  // sum1记录选子节点的和,sum2记录不选子节点的和
    
    for(int i = 0; i < g[x].size(); i++) {
        int y = g[x][i];  // 遍历x的所有子节点y
        if(y == f[x]) continue;  // 避免回溯到父节点
        
        dfs(y);  // 递归处理子节点
        
        // 累加子节点选或不选的情况
        sum1 += dp[y][1];  // 所有子节点都选的情况(实际不会这样用)
        sum2 += dp[y][0];  // 所有子节点都不选的情况
        
        // 正确的状态转移:
        // 如果选x,那么子节点y不能选,所以加上dp[y][0]
        dp[x][1] += dp[y][0];
        // 如果不选x,那么子节点y可选可不选,取最大值
        dp[x][0] += max(dp[y][0], dp[y][1]);
        
        // 原代码中这一行被注释掉了,其实不需要在dfs过程中更新ans
        // ans = max(ans,max(dp[x][0],dp[x][1]));
    }
}

int main() {
    cin >> n;
    // 读取每个节点的快乐指数
    for(int i = 1; i <= n; i++) cin >> a[i];
    
    // 建立树结构,注意题目中第一个数是下属,第二个数是上司
    for(int i = 1; i < n; i++) {
        int x, y; 
        cin >> x >> y;
        g[y].push_back(x);  // y是x的上司,所以x是y的子节点
        f[x] = y;           // 记录x的父节点是y
    }
    
    // 寻找根节点(没有父节点的节点)
    for(int i = 1; i <= n; i++) 
        if(f[i] == 0) rt = i;
    
    // 从根节点开始进行DFS遍历
    dfs(rt);
    
    // 遍历所有节点,找出最大值(其实只需要看根节点即可)
    for(int i = 1; i <= n; i++) 
        ans = max(ans, max(dp[i][0], dp[i][1]));
    
    cout << ans;
    return 0;
}

 

posted @ 2025-06-12 15:37  CRt0729  阅读(38)  评论(0)    收藏  举报