树上DP - 洛谷P1352 - 没有上司的舞会

https://www.luogu.com.cn/problem/P1352

 

 

开二维数组  dp[ Maxsize ][ 2 ]

dp[ i ][ 0 ] 表示上司 i 不参加舞会的最优解, dp[ i ][ 1 ]不参加舞会的最优解。

易得方程:dp[ i ][ 0 ] = 每一个孩子节点 x :  dp[ i ][ 0 ]  += max( dp[ x ][ 0 ] , dp[ x ][ 1 ])  ;  dp[ i ][ 1 ] = 每一个孩子节点 x : dp[ i ][ 1 ]  += max( 0, dp[ x ][ 0 ])

记得在初始化时对每一个 dp[ i ][ 1 ] 初始化为其本身的点权

由于我们可以用dp[ i ][ 1 ]记录点权(同时也是初始化的过程), 就不需要另外再开一个数组记录点权了,节省了空间。

 1 #include <iostream>
 2 #include <vector>
 3 #define MAX(a,b) (a>b?a:b)
 4 #define Maxsize 6000+1
 5 using namespace std;
 6 bool not_root[Maxsize];
 7 bool vis[Maxsize];
 8 int dp[Maxsize][2]; // dp[i][0] 不选用 i 的最优解 , dp[i][1] 选用 i 的最优解
 9 vector<int> vec[Maxsize];
10 void dfs(int root){
11     for (auto it = vec[root].begin(); it != vec[root].end(); it++) {
12         if(!vis[*it]){
13             vis[*it] = true;
14             dfs(*it);
15             vis[*it] = false;
16         }
17     }
18     for (auto it = vec[root].begin(); it != vec[root].end(); it++) {
19         if(vis[*it])continue;
20         dp[root][0] += MAX(dp[*it][0],dp[*it][1]);
21         dp[root][1] += MAX(dp[*it][0],0);
22     }
23 }
24 int main(){
25     int n;
26     int a,b;
27     cin >> n;
28     for (int i = 1; i <= n; i++) {
29         cin >> dp[i][1];
30     }
31     for (int i = 1; i <= n; i++) {
32         cin >> a >> b;  // 子 , 父
33         vec[b].push_back(a);
34         not_root[a] = true;
35     }
36     int root = -1;
37     for (int i = 1; i <= n; i++) {
38         if(!not_root[i]){
39             root = i;
40             break;
41         }
42     }
43     dfs(root);
44     cout << MAX(dp[root][0],dp[root][1]);
45     return 0;
46 }

 

posted @ 2020-03-17 11:10  popozyl  阅读(200)  评论(0编辑  收藏  举报