HDU 1520 Anniversary party [树形DP]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520

题目大意:给出n个带权点,他们的关系可以构成一棵树,问从中选出若干个不相邻的点可能得到的最大值为多少

解题思路:简单的树形DP

用dp[i][0]表示以i为根的树上不取i的状态下能得到的最大值

用dp[i][1]表示以i为根的树取i的状态下能得到的最大值

状态转移方程

dp[i][0]=∑(max(dp[son(i)][0],dp[son(i)][1]))

dp[i][1]=∑(dp[son(i)][0])+value[i]

代码如下:

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 //#pragma comment(linker,"/STACK:102400000,102400000")
 8 #define FFF 6005
 9 int value[6005];
10 int dp[FFF][2];
11 //dp[i][1]表示取i的最大值,dp[i][0]表示不取i的最大值
12 int v[FFF*2],first[FFF],next[FFF*2],e;
13 bool vis[FFF];
14 void link(int x,int y)
15 {
16     v[e]=y;
17     next[e]=first[x];
18     first[x]=e++;
19 }
20 int dfs(int now)
21 {
22     int ans1=0,ans0=0;
23         //ans1 取now的值 ans0 不取now的值
24     int k,va;
25     for(k=first[now];k!=-1;k=next[k])
26     {
27         va=v[k];
28         if(!vis[va])
29         {
30             vis[va]=true;
31             dfs(va);
32             ans1+=dp[va][0];
33             ans0+=max(dp[va][1],dp[va][0]);
34         }
35     }
36     dp[now][0]=ans0;
37     dp[now][1]=ans1+value[now];
38     return max(dp[now][0],dp[now][1]);
39 }
40 int main()
41 {
42     int n;
43     while(~scanf("%d",&n)){    
44         for(int i=1;i<=n;i++)
45         {
46             dp[i][0]=dp[i][1]=0;
47             scanf("%d",&value[i]);
48             first[i]=-1;
49         }
50         int x,y;
51         e=0;
52         while(scanf("%d%d",&x,&y),x||y)
53         {
54             link(x,y);
55             link(y,x);
56         }
57         memset(vis,false,sizeof(vis));
58         vis[1]=true;
59         cout<<dfs(1)<<endl;
60     }
61     return 0;
62 }
View Code
原文地址:https://www.cnblogs.com/wuwing/p/3678792.html