专栏文章
P1352 没有上司的舞会
P1352题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqbqcu8
- 此快照首次捕获于
- 2025/12/04 02:11 3 个月前
- 此快照最后确认于
- 2025/12/04 02:11 3 个月前
题目描述
某大学有
n 个职员,编号为 1 到 n。他们之间有从属关系,形成一棵以校长为根的树,父节点是子节点的直接上司。现在要举办一个舞会,邀请某些职员可以增加一定的快乐指数 r_i,但如果某个职员的直接上司参加了舞会,那么这个职员就不会参加。任务是计算出邀请哪些职员可以使快乐指数最大,并输出最大快乐指数。输入输出格式
- 输入:
- 第一行是一个整数
n,表示职员数量。 - 接下来的
n行,每行一个整数,表示每个职员的快乐指数r_i。 - 接下来的
n-1行,每行两个整数l和k,表示k是l的直接上司。
- 第一行是一个整数
- 输出:
- 输出一个整数,表示最大的快乐指数。
解题思路
-
树的构建:
- 使用邻接表来存储树结构。读取每对
(l, k),表示k是l的直接上司,将l添加到k的子节点列表中。
- 使用邻接表来存储树结构。读取每对
-
动态规划定义:
- 定义
dp[x][0]表示以x为根的子树中,x不参加舞会时的最大快乐值。 - 定义
dp[x][1]表示以x为根的子树中,x参加舞会时的最大快乐值。
- 定义
-
状态转移方程:
- 如果
x不参加舞会,那么它的子节点可以自由选择是否参加舞会: - 如果
x参加舞会,那么它的所有子节点都不能参加舞会:
- 如果
-
递归计算:
- 使用深度优先搜索(DFS)从根节点开始递归计算
dp数组。对于每个节点x,先递归计算其所有子节点的dp值,然后根据状态转移方程更新dp[x][0]和dp[x][1]。
- 使用深度优先搜索(DFS)从根节点开始递归计算
-
结果输出:
- 最终结果为
max(dp[root][0], dp[root][1]),即根节点不参加或参加舞会的最大快乐值。
- 最终结果为
代码实现
以下是用 C++ 实现的代码示例:
CPP#include <bits/stdc++.h>
using namespace std;
const int MAXN = 6010;
vector<int> son[MAXN];
int dp[MAXN][2], h[MAXN], n;
void dfs(int x) {
dp[x][0] = 0;
dp[x][1] = h[x];
for (int i = 0; i < son[x].size(); i++) {
int y = son[x][i];
dfs(y);
dp[x][0] += max(dp[y][0], dp[y][1]);
dp[x][1] += dp[y][0];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
son[y].push_back(x);
}
dfs(1); // 假设 1 是根节点
cout << max(dp[1][0], dp[1][1]) << endl;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...