题面

大秦为你打开题目传送门

题目描述

某大学有 $n$ 个职员,编号为 $1\ldots n$。

他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。

现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 $r_i$,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。

所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入格式

输入的第一行是一个整数 $n$。

第 $2$ 到第 $(n + 1)$ 行,每行一个整数,第 $(i+1)$ 行的整数表示 $i$ 号职员的快乐指数 $r_i$。

第 $(n + 2)$ 到第 $2n$ 行,每行输入一对整数 $l, k$,代表 $k$ 是 $l$ 的直接上司。

输出格式

输出一行一个整数代表最大的快乐指数。

样例 #1

样例输入 #1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5

样例输出 #1

1
5

提示

数据规模与约定

对于 $100%$ 的数据,保证 $1\leq n \leq 6 \times 10^3$,$-128 \leq r_i\leq 127$,$1 \leq l, k \leq n$,且给出的关系一定是一棵树。

思路

很简单,直接做DP状态为 $dp[u][0/1]$ 表示这个点的人参加还是不参加的最大值。
有了这个状态,方程简直就是信手拈来:
$$
dp[u][0] = \sum\limits_{v ∈ son(u)}\max{dp[v][0], dp[v][1]}\
dp[u][1] = \sum\limits_{v ∈ son(u)}dp[v][0]
$$
这个是真的太简单了(我都会做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;

int n;
vector<int> v[6005];
int a[6005];
int vis[6005];
int dp[6005][2];

void Input(){
cin>>n;
for(int i=1; i<=n; i++){
cin>>a[i];
}
int x, y;
while (cin>>x>>y && (x || y))
{
v[y].push_back(x);
vis[x] = 1;
}
}
void treedp(int now)
{
dp[now][0] = 0;
dp[now][1] = a[now];
int sz = v[now].size();
for(int i=0; i<sz; i++){
int son = v[now][i];
treedp(son);
dp[now][0] += max(dp[son][0], dp[son][1]);
dp[now][1] += dp[son][0];
}
}

void Work(){
int now = 1;
while (vis[now]){
now++;
}
treedp(now);
cout<<max(dp[now][0], dp[now][1]);
}

int main()
{
ios::sync_with_stdio(0);

Input();
Work();
return 0;
}