URAL-1039 Anniversary Party---树形DP入门题

题目链接:

https://cn.vjudge.net/problem/URAL-1039

题目大意:

开一个party,每个员工都有一个欢乐值,只有是上司和下属不同时存在时才能欢乐,问怎样安排能有最大的欢乐值。

解题思路:

首先建立上司下属的树形结构,进行树形DP

dp[i][0]表示第i人不参加聚会时,以i为根节点的子树的最大欢乐值

dp[i][1]表示第i人参加聚会时,以i为根节点的子树的最大欢乐值

答案就为max(dp[root][0], dp[root][1])

根据边找到root节点

递推方程:

dp[i][0] = sum(max(dp[son][0], dp[son][1]))第i节点不去,它的儿子可以去,也可以不去

dp[i][1] = a[x] + sum(dp[son][0])    i节点去,那么它的儿子一定不可以去

用dfs来更新dp

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e4 + 10;
 4 vector<int>Map[maxn];
 5 int dp[maxn][2], a[maxn], father[maxn];
 6 void dfs(int x)
 7 {
 8     dp[x][1] = a[x];
 9     for(int i = 0; i < Map[x].size(); i++)
10     {
11         int son = Map[x][i];
12         dfs(son);
13         dp[x][0] = max(dp[x][0] + dp[son][1], dp[x][0] + dp[son][0]);
14         dp[x][1] = dp[x][1] + dp[son][0];
15     }
16     //cout<<x<<dp[x][0]<<dp[x][1]<<endl;
17 }
18 int main()
19 {
20     int n;
21     while(cin >> n)
22     {
23         memset(dp, 0, sizeof(dp));
24         for(int i = 1; i <= n; i++)
25         {
26             scanf("%d", &a[i]);
27             father[i] = -1;
28             Map[i].clear();
29         }
30         int u, v;
31         while(scanf("%d%d", &u, &v) != EOF)
32         {
33             if(!u && !v)break;
34             Map[v].push_back(u);
35             father[u] = v;
36         }
37         int root = 1;
38         while(father[root] != -1)
39         {
40             root = father[root];
41         }
42         dfs(root);
43         cout<<max(dp[root][0], dp[root][1])<<endl;
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/fzl194/p/9320609.html