树形DP URAL 1039 Anniversary Party

题目传送门

 1 /*
 2     题意:上司在,员工不在,反之不一定。每一个人有一个权值,问权值和最大多少。
 3     树形DP:把上司和员工的关系看成根节点和子节点的关系,两者有状态转移方程:
 4             dp[rt][0] += max (dp[son][1], dp[son][0]);    //上司不去
 5             dp[rt][1] += dp[son][0];                    //上司去,员工都不去
 6 */
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <algorithm>
10 #include <vector>
11 #include <cmath>
12 using namespace std;
13 
14 const int MAXN = 6e3 + 10;
15 const int INF = 0x3f3f3f3f;
16 bool vis[MAXN];
17 vector<int> edge[MAXN];
18 int dp[MAXN][2];
19 int n;
20 
21 void DFS(int rt)
22 {
23     vis[rt] = true;
24     dp[rt][0] = 0;
25     for (int i=0; i<edge[rt].size (); ++i)
26     {
27         int son = edge[rt][i];
28         if (!vis[son])
29         {
30             DFS (son);
31             dp[rt][0] += max (dp[son][1], dp[son][0]);
32             dp[rt][1] += dp[son][0];
33         }
34     }
35 }
36 
37 int main(void)        //URAL 1039 Anniversary Party
38 {
39 //    freopen ("URAL_1039.in", "r", stdin);
40 
41     while (scanf ("%d", &n) == 1)
42     {
43         memset (vis, false, sizeof (vis));
44         memset (dp, 0, sizeof (dp));
45         for (int i=1; i<=n; ++i)    scanf ("%d", &dp[i][1]);
46 
47         int l, k;
48         while (scanf ("%d%d", &l, &k) == 2)
49         {
50             if (l == 0 && k == 0)    break;
51             vis[l] = true;
52             edge[l].push_back (k);
53             edge[k].push_back (l);
54         }
55 
56         int root = 0;
57         for (int i=1; i<=n; ++i)
58         {
59             if (!vis[i])    {root = i;    break;}
60         }
61 
62         memset (vis, false, sizeof (vis));    DFS (root);
63         printf ("%d
", max (dp[root][0], dp[root][1]));
64     }
65 
66     return 0;
67 }
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4646064.html