CH5401 没有上司的舞会【树形DP】

5401 没有上司的舞会 0x50「动态规划」例题

描述

Ural大学有N名职员,编号为1~N。他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。每个职员有一个快乐指数,用整数 H_i 给出,其中 1≤i≤N。现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。

输入格式

第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数H_i。(-128<=H_i<=127)
接下来N-1行,每行输入一对整数L, K。表示K是L的直接上司。
最后一行输入0,0。

输出格式

输出最大的快乐指数。

样例输入

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出

5

题意:

有一棵树,表示的是上下隶属关系。这n个人的一部分人要去参加舞会,但是不希望和父亲节点一起参加。每个人有一个happy值。求最大的happy值之和。

思路:

对于每一个节点x,都有两种状态:1.参加舞会 2.不参加舞会

如果x参加舞会,那么他的所有孩子都不能参加舞会

如果x不参加舞会,那么他的孩子可以参加,也可以不参加。

每一个节点x的最优解,都由他的孩子的最优解决定。

用二维数组dp[i][0], dp[i][1]分别表示i节点不参加时的最大值和i节点参加时的最大值。

 1 //#include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<vector>
 8 #include<map>
 9 
10 #define inf 0x3f3f3f3f
11 using namespace std;
12 typedef long long LL;
13 
14 int n;
15 const int maxn = 6005;
16 int happy[maxn];
17 vector<int>son[maxn];
18 int dp[maxn][2];
19 bool has_father[maxn];
20 
21 int dfs(int rt)
22 {
23     dp[rt][0] = 0;
24     dp[rt][1] = happy[rt];
25     for(int i = 0; i < son[rt].size(); i++){
26         int y = son[rt][i];
27         dfs(y);
28         dp[rt][0] += max(dp[y][0], dp[y][1]);
29         dp[rt][1] += dp[y][0];
30     }
31 }
32 
33 int main()
34 {
35     scanf("%d", &n);
36     for(int i = 1; i <= n; i++){
37         scanf("%d", &happy[i]);
38     }
39     for(int i = 1; i < n; i++){
40         int x,y;
41         scanf("%d%d", &x, &y);
42         has_father[x] = true;
43         son[y].push_back(x);
44     }
45     int root;
46     for(int i = 1; i <= n; i++){
47         if(!has_father[i]){
48             root = i;
49             break;
50         }
51     }
52 
53     dfs(root);
54     int ans = max(dp[root][0], dp[root][1]);
55     printf("%d
", ans);
56     return 0;
57 }
原文地址:https://www.cnblogs.com/wyboooo/p/9760282.html