poj 2342 hdu 1520【树形dp】

poj 2342

给出每个顶点的happy值,还有若干组两个顶点L,K关系,表示K是L的上司。求当K、L不同时出现时获得的happy值的最大和。

设dp[u][0]表示不选u结点时获得的最大值,dp[u][1]表示选u结点时获得的最大值。则有:

   dp[u][0]+=max(dp[v][0],dp[v][1]),dp[u][1]+=dp[v][0](u为v的父节点)

当父亲节点用有向边连向子节点时,会形成一颗树,自然就只有一个根。那么从根开始dfs就行了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxn = 6200;
 8 int dp[maxn][2], vis[maxn], a[maxn];
 9 vector<int> tree[maxn];
10 int N;
11 
12 void Init()
13 {
14     for (int i = 1; i <= N; i++) {
15         cin >> a[i];
16         tree[i].clear(), vis[i] = 0;
17     }
18     int L, K;
19     while (cin>>L>>K)
20     {
21         if (L == 0 && K == 0) break;
22         tree[K].push_back(L);
23         vis[L] = 1;
24     }
25     tree[0].clear();//找根
26     for(int i=1;i<=N;i++)
27         if (!vis[i]) {
28             tree[0].push_back(i);
29             break;//只有一个根,找到后就break
30         }
31 }
32 
33 void dfs(int u)
34 {
35     dp[u][0] = 0;
36     dp[u][1] = a[u];
37     for (int i = 0; i < tree[u].size(); i++)
38     {
39         int v = tree[u][i];
40         dfs(v);
41         dp[u][0] += max(dp[v][0], dp[v][1]);
42         dp[u][1] += dp[v][0];
43     }
44 }
45 
46 void Solve()
47 {
48     int root = tree[0][0];
49     dfs(root);
50     cout << max(dp[root][0], dp[root][1]) << endl;
51 }
52 
53 int main()
54 {
55     while (cin>>N)
56     {
57         Init();
58         Solve();
59     }
60     return 0;
61 }
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 const int maxn=6200;
 9 int dp[maxn][2],rat[maxn],f[maxn],vis[maxn];
10 vector<int> tree[maxn];
11 
12 void dfs(int u)
13 {
14     vis[u]=1;
15     dp[u][0]=0;
16     dp[u][1]=rat[u];
17     int len=tree[u].size();
18     for(int i=0;i<len;i++){
19         int v=tree[u][i];
20         if(vis[v]) continue;
21         dfs(v);
22         dp[u][0]+=max(dp[v] [1],dp[v][0]);
23         dp[u][1]+=dp[v][0];
24     }
25 }
26 
27 int main()
28 {
29     int N;
30     while(scanf("%d",&N)==1)
31     {
32         for(int i=1;i<=N;i++){
33             scanf("%d",&rat[i]);
34             vis[i]=0;f[i]=-1;
35             tree[i].clear();
36         }
37         int a,b;
38         while(scanf("%d%d",&a,&b))
39         {
40             if(a==0&&b==0) break;
41             f[a]=b;
42             tree[b].push_back(a);
43         }
44         int root;
45         for(int i=1;i<=N;i++){
46             if(f[i]==-1){
47                 root=i;
48                 break;
49             }
50         }
51         dfs(root);
52         cout<<max(dp[root][0],dp[root][1])<<endl;
53     }
54     return 0;
55 }
又写了一遍
原文地址:https://www.cnblogs.com/zxhyxiao/p/7580515.html