洛谷传送门
题目描述
某大学有 N N N个职员,编号为 1 ∼ N 1\sim N 1∼N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 R i R_i Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
输入输出格式
输入格式:
第一行一个整数N。( 1 ≤ N ≤ 6000 1\le N\le 6000 1≤N≤6000)
接下来 N N N行,第 i + 1 i+1 i+1行表示i号职员的快乐指数 R i R_i Ri。( − 128 ≤ R i ≤ 127 -128\le Ri\le 127 −128≤Ri≤127)
接下来 N − 1 N-1 N−1行,每行输入一对整数 L , K L,K L,K。表示 K K K是 L L L的直接上司。
最后一行输入 0 0 0\ 0 0 0
输出格式:
输出最大的快乐指数。
输入输出样例
输入样例#1:
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
输出样例#1:
5
解题分析
树上
0
/
1
D
P
0/1DP
0/1DP。 设
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]表示不选这个点,
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1]表示选这个点, 那么转移方程为:
d
p
[
i
]
[
0
]
=
∑
j
,
j
∈
s
o
n
[
i
]
m
a
x
(
d
p
[
j
]
[
0
]
,
d
p
[
j
]
[
1
]
)
d
p
[
i
]
[
1
]
=
∑
j
,
j
∈
s
o
n
[
i
]
d
p
[
j
]
[
0
]
+
v
a
l
[
i
]
dp[i][0]=\sum_{j,j\in son[i]}max(dp[j][0],dp[j][1]) \\ dp[i][1]=\sum_{j,j\in son[i]}dp[j][0]+val[i]
dp[i][0]=j,j∈son[i]∑max(dp[j][0],dp[j][1])dp[i][1]=j,j∈son[i]∑dp[j][0]+val[i]
代码如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <cmath>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 10500
bool neg;
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc)
if (c == '-') neg = true;
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
if(neg) neg = false, x = -x;
}
int dot, cnt;
int dp[MX][2], head[MX], val[MX], deg[MX];
struct Edge {int to, nex;} edge[MX << 1];
IN void add(R int from, R int to) {edge[++cnt] = {to, head[from]}, head[from] = cnt;}
void DFS(R int now)
{
dp[now][0] = 0, dp[now][1] = val[now];
for (R int i = head[now]; i; i = edge[i].nex)
{
DFS(edge[i].to);
dp[now][0] += std::max(dp[edge[i].to][0], dp[edge[i].to][1]);
dp[now][1] += dp[edge[i].to][0];
}
}
int main(void)
{
int a, b;
in(dot);
for (R int i = 1; i <= dot; ++i) in(val[i]);
for (R int i = 1; i < dot; ++i) in(a), in(b), add(b, a), ++deg[a];
for (R int i = 1; i <= dot; ++i)
if(!deg[i]) {DFS(i); printf("%d", std::max(dp[i][0], dp[i][1])); break;}
}