题目链接: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 }