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

 

你可能感兴趣的:(part)