hdu 1561 树形dp

思路:树形结构 加一个点(0点)构成森林 然后树形dp。。

状态转移方程:

dp[x][j] = max(dp[x][j], dp[cnt][j-i] + dp[x][i]);

表示第x个的子节点中取j个 为最优解 cnt为x的某个子节点

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#define N 10005<<1
#define INF 10000000
#define LL long long
#define eps 10E-9
#define mem(a)  memset(a,0,sizeof(a))
#define mem1(a)  memset(a,-1,sizeof(a))
#define w(a)   while(a)
#define s(a)   scanf("%d",&a)
#define ss(a,b)   scanf("%d%d",&a,&b)
#define sss(a,b,c)   scanf("%d%d%d",&a,&b,&c)
#define PI acos(-1.0)
using namespace std;
int n, m;
int dp[202][202];
int i_th_son[202][202];
int num_son[202];
bool vis[202];
void tree_dp(int x){
     vis[x] = true;
     for(int i=1; i<=num_son[x]; i++){
        int cnt = i_th_son[x][i];
        if(!vis[cnt]) tree_dp(cnt);
        for(int j=m; j>=2; j--){
            for(int i=1; i<j; i++){
                if(dp[cnt][j-i]>-1 && dp[x][i]>-1) dp[x][j] = max(dp[x][j], dp[cnt][j-i] + dp[x][i]);
            }
        }
     }
}
int main(){
    w(~ss(n,m) && (n||m)){
        int a, b;
        dp[0][1] = 0;
        mem(num_son);
        for(int  i=1; i<=n; i++){
            ss(a,b);
            dp[i][1] = b;
            i_th_son[a][++num_son[a]] = i;
        }
        m++;//加点
        for(int i=0; i<=n; i++){
            dp[i][0] = 0;
            vis[i] = false;
            for(int j=2; j<=m; j++){
                dp[i][j] = -1;
            }
        }
        tree_dp(0);
        cout<<dp[0][m]<<endl;
    }
    return 0;
}


posted @ 2017-06-26 09:24  yxysuanfa  阅读(97)  评论(0编辑  收藏  举报