按以下要求写一段c语言代码:某学校有 n 个职员,编号为 1到n。 他们之间有上下级关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。 现在有个周年庆舞会,舞会每邀请来一个职员都会增加一定的快乐指数vali,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。 所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。 输入 输入的第一行是一个整数n (1<=n<=100000)。 第2到第n+1行,每行一个整数,第i+1行的整数表示i号职员的快乐指数val (-200<=val<=200)。 第n+2到2n行,每行输入一对整数l、k,表示k是l的直接上司。 输出 输出一行一个整数代表最大的快乐指数。
时间: 2024-02-09 07:12:32 浏览: 101
这道题可以使用动态规划来解决。我们设f[i][0/1]表示以i为根节点的子树中,i参加舞会/不参加舞会所获得的最大快乐值。那么可以得到状态转移方程:
f[i][0] = ∑max{f[j][0], f[j][1]} + val[i] (j是i的儿子节点)
f[i][1] = ∑f[j][0] (j是i的儿子节点)
最终的结果就是max{f[1][0], f[1][1]}。
以下是对应的C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 100005
int val[MAXN], head[MAXN], to[MAXN], nxt[MAXN];
int f[MAXN][2];
void add_edge(int u, int v) {
static int tot = 0;
tot++;
to[tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
void dfs(int u) {
f[u][0] = 0;
f[u][1] = val[u];
for (int i = head[u]; i; i = nxt[i]) {
int v = to[i];
dfs(v);
f[u][0] += f[v][1];
f[u][1] += f[v][0];
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &val[i]);
}
for (int i = 2; i <= n; i++) {
int boss;
scanf("%d", &boss);
add_edge(boss, i);
}
dfs(1);
printf("%d\n", f[1][0] > f[1][1] ? f[1][0] : f[1][1]);
return 0;
}
```
这里使用邻接表存图,add_edge函数用于添加边。在dfs函数中,我们首先初始化f[u][0]和f[u][1],然后遍历u的所有儿子节点v,分别计算f[v][0]和f[v][1],最后根据上述状态转移方程计算f[u][0]和f[u][1]。最终结果就是max{f[1][0], f[1][1]}。
阅读全文