地址 https://www.acwing.com/solution/content/20539/
Ural大学有N名职员,编号为1~N。 他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。 每个职员有一个快乐指数,用整数 Hi 给出,其中 1≤i≤N。 现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。 在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。 输入格式 第一行一个整数N。 接下来N行,第 i 行表示 i 号职员的快乐指数Hi。 接下来N-1行,每行输入一对整数L, K,表示K是L的直接上司。 输出格式 输出最大的快乐指数。 数据范围 1≤N≤6000, −128≤Hi≤127 输入样例: 7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 输出样例: 5
算法1
树形DP
dp[i][j] 表示 点i在j状态(0 1选择或者不选择)下的最多快乐指数
由于i点未选中 那么子树节点j点可选不可选
dp[i][0] = max(dp[j][0],dp[j][1]); j为i的子树
由于i点选中 子节点j一定不可选
dp[i][1] = max(dp[[j][1]);
使用了vector来表示树 未使用链式前向星
#include <iostream> #include <vector> #include <algorithm> using namespace std; int n; const int N = 6010; int happy[N]; int f[N][2]; int has_father[N]; vector<int> g[N]; void dfs(int curr) { f[curr][1] += happy[curr]; for (int i = 0; i < g[curr].size(); i++) { int son = g[curr][i]; dfs(son); f[curr][0] += max(f[son][0], f[son][1]); f[curr][1] += f[son][0]; } } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> happy[i]; for (int i = 1; i < n; i++) { int a; int b; cin >> a; cin >> b; g[b].push_back(a); has_father[a] = 1; } //寻找起点 int idx = 1; while (has_father[idx]) idx++; dfs(idx); cout << max(f[idx][1], f[idx][0]); return 0; }