没有上司的舞会

 树形dp的基础题。

由于是一个树形结构,所以我们和容易就可以得到一个拓扑图,由此我们在存图时只需要存下每个点的入度,然后对入度为0的节点进行搜索dp即可。

状态表示为f[i][2],f[i][0]表示第i个人不参加宴会的最大快乐指数,f[i][1]表示第i个人参加宴会的快乐指数,所以我们的状态转移方程为:

1 f[i][1] = max(w[i], f[j1][0] + f[j2][0] + ..... + f[jn][0]); // 当第i个人参加宴会时他的下属都不能参加宴会,所以需要求得每个下属不参加宴会时的快乐值的和。
2 f[i][0] = max(f[j1][1], f[j1][0]) + max(f[j2][1], f[j2][0]) + ..... + max(f[jn][0], f[n1][1]); // 当第i个人不参加宴会时他的下属可以参加也可以不参加,所以就是max(f[j1....jn][0], f[j1....jn][1])。

代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <cmath>
 6 
 7 using namespace std;
 8 
 9 typedef long long LL;
10 
11 const int N = 6010;
12 
13 int n, m;
14 int w[N], h[N], ne[N], e[N], idx;
15 int f[N][2];
16 int in[N];
17 
18 void add(int a, int b) 
19 {
20     e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
21 }
22 
23 void dfs(int u)
24 {
25     int res = 0;
26     for (int i = h[u]; i != -1; i = ne[i])
27     {
28         int j = e[i];
29         dfs(j);
30         f[u][0] += max(f[j][0], f[j][1]);
31         res = max(res, res + f[j][0]);
32     }
33 
34     f[u][1] = max(w[u], w[u] + res);
35 }
36 
37 int main()
38 {
39     cin >> n;
40     memset(h, -1, sizeof h);
41     for (int i = 1; i <= n; i ++ ) cin >> w[i];
42     for (int i = 1; i <= n - 1; i ++ ) 
43     {
44         int a, b;
45         cin >> a >> b;
46         add(b, a);
47         in[a] ++ ;
48     }
49 
50     int t = 0;
51     for (int i = 1; i <= n; i ++ ) 
52         if (!in[i]) 
53         {
54             t = i;
55             break;
56         }
57     
58     dfs(t);
59 
60     cout << max(f[t][1], f[t][0]) << endl;
61     
62     return 0;
63 }

 

posted @ 2021-04-12 02:23  筱翼深凉  阅读(61)  评论(0编辑  收藏  举报