codevs 1380/HDU 1520 树形dp

1380 没有上司的舞会

 

时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond

题目描述 Description

      Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

输入描述 Input Description

第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。

输出描述 Output Description

输出最大的快乐指数。

样例输入 Sample Input

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

各个测试点1s

题意:n个职员 都拥有一个快乐值 但是,没有职员愿和直接上司一起与会(允许同时不出席)  问快乐值的和的最大值

题解:树形dp 从root节点开始向下遍历到叶子节点   dp[i][1] 代表 节点(职员)i参见宴会的快乐值和的最大值 

        dp[i][0]代表  节点(职员)i不参加宴会的快乐值和的最大值

        转移方程如下:x=f[i] x为i的父亲节点

        dp[x][1]+=dp[i][0]; 

        dp[x][0]+=max(dp[i][1],dp[i][0]);

 codevs AC代码

 1 #include<bits/stdc++.h>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 #include<algorithm>
 7 #define ll __int64
 8 using namespace std;
 9 int v[6005];
10 int dp[6005][2];
11 int f[6005];
12 int n;
13 int l,k;
14 void tree(int x)
15 {
16     v[x]=1;
17     for(int i=1;i<=n;i++)
18     {
19         if(v[i]==0&&f[i]==x)
20         {
21             tree(i);
22             dp[x][1]+=dp[i][0];
23             dp[x][0]+=max(dp[i][1],dp[i][0]);
24         }
25 
26     }
27 }
28 int main()
29 {
30     scanf("%d",&n);
31     int root=1;
32     for(int i=1;i<=n;i++)
33         f[i]=0;
34     for(int i=1;i<=n;i++)
35         scanf("%d",&dp[i][1]);
36     for(int i=1;i<=n-1;i++)
37     {
38         scanf("%d %d",&l,&k);
39         f[l]=k;
40     }
41     scanf("%d %d",&l,&k);
42     while(f[root]!=0)
43         root=f[root];
44     tree(root);
45     printf("%d
",max(dp[root][1],dp[root][0]));
46     return 0;
47 }

hdu AC 代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<vector>
 5 using namespace std;
 6 int n;
 7 int dp[6002][2];
 8 int l,k;
 9 int f[6002];
10 int v[6002];
11 vector<int> ve[6002];
12 void dfs(int x)
13 {
14     v[x]=1;
15     for(int i=0;i<ve[x].size();i++)
16     {
17         if(v[ve[x][i]]==0)
18         {
19         dfs(ve[x][i]);
20         dp[x][1]+=dp[ve[x][i]][0];
21         dp[x][0]+=max(dp[ve[x][i]][0],dp[ve[x][i]][1]);
22         }
23     }
24 }
25 int main ()
26 {
27     while(scanf("%d",&n)!=EOF)
28     {
29         int root=1;
30         memset(dp,0,sizeof(dp));
31         for(int i=1;i<=n;i++)
32            f[i]=0;
33         memset(v,0,sizeof(v));
34         for(int i=1;i<=n;i++)
35             {
36                 scanf("%d",&dp[i][1]);
37                 ve[i].clear();
38             }
39         while(scanf("%d %d",&l,&k))
40         {
41           if(l==0&&k==0)
42             break;
43            f[l]=k;
44            ve[k].push_back(l);
45         }
46         while(f[root]!=0)
47         {
48             root=f[root];
49         }
50         dfs(root);
51       printf("%d
",max(dp[root][0],dp[root][1]));
52     }
53     return  0;
54 }
原文地址:https://www.cnblogs.com/hsd-/p/5670651.html