poj2486(树形dp)

http://poj.org/problem?id=2486

题意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值

 1 #include <iostream>

 2 #include <cstring>

 3 #include <vector>

 4 #include <cstdio>

 5 using namespace std;

 6 inline int max(int a,int b) {return a>b? a:b;}

 7 const int Ni = 105;

 8 int n,m;

 9 bool vis[Ni];

10 int weg[Ni];

11 int dp[2][Ni][211];

12 vector<int> eg[Ni];

13 void dfs(int p)

14 {

15     int i,j,k,son;

16     vis[p]=1;

17     for(i=0;i<=m;i++)

18     {dp[0][p][i]=dp[1][p][i]=weg[p];}

19     for(i=0;i<eg[p].size();i++)

20     {

21         son=eg[p][i];

22         if(vis[son]) continue;

23         dfs(son);

24         for(j=m;j>=0;j--)

25         {

26             for(k=0;k<=j;k++)

27             {

28                 //从p往son分支走得到结果回到p,人留在p

29                 dp[0][p][j+2] = max(dp[0][p][j+2],dp[0][p][j-k]+dp[0][son][k]);

30                 //从son往p走,再回到p的son,人留在son

31                 dp[1][p][j+2] = max(dp[1][p][j+2],dp[1][p][j-k]+dp[0][son][k]);

32                 //从p往son分支走得到结果

33                 dp[1][p][j+1] = max(dp[1][p][j+1],dp[0][p][j-k]+dp[1][son][k]);

34             }

35         }

36     }

37 }

38 int main()

39 {

40     while(~scanf("%d%d",&n,&m))

41     {

42         memset(vis,0,sizeof(vis));

43         memset(dp,0,sizeof(dp));

44         for(int i=1;i<=n;i++)

45         {

46             eg[i].clear();

47             scanf("%d",weg+i);

48         }

49         for(int i=1;i<n;i++)

50         {

51             int u,v;

52             scanf("%d%d",&u,&v);

53             eg[u].push_back(v);

54             eg[v].push_back(u);

55         }

56         dfs(1);

57         printf("%d\n",dp[1][1][m]);

58     }

59     return 0;

60 }

 

你可能感兴趣的:(poj)