刚开始我以为是比较熟悉的树形dp+背包,但一直wa,网上的代码是非递归的,看到我头晕,看了大牛的代码后才发现有Trick...
       发下代码,给有同样问题的人参考下

/*
    题意:给出一棵树,每个点有权值,要取得这个权值需要代价,通过父亲后才能到达儿子
    问能量有限时获得的最大值
    直接tree dp+背包
    注意的是,每个点至少要有一个人,即使没有bug!
*/

#include
<cstdio>
#include
<cstring>
#include
<vector>
using namespace std;

const int MAXN=110;
const int INF=1000000000;

int n,m;
vector
<int>G[MAXN];
int bug[MAXN],brain[MAXN];
bool vi[MAXN];
int dp[MAXN][MAXN];

void dfs(int u){
    vi[u]
=1;
    
for(int j=1;j<=m;j++)dp[u][j]=-INF;
    dp[u][
0]=0;
    
int t=(bug[u]+19)/20;
    
//if(!t&&brain[u])t=1; 这样写会错
    /*
        2 1
        0 1
        0 1
        1 2
        答案是2
        上面那样写答案是1
    
*/

    
if(t<=m)dp[u][t]=brain[u];
    
for(int i=0;i<G[u].size();i++){
        
int v=G[u][i];
        
if(vi[v])continue;
        dfs(v);
        
for(int j=m;j>t;j--)
            
for(int k=1;j-k>=t;k++)
                
if(dp[u][j-k]!=-1&&dp[v][k]!=-1&&dp[u][j]<dp[u][j-k]+dp[v][k])
                    dp[u][j]
=dp[u][j-k]+dp[v][k];
    }

    
//一定要有这一句,占领父亲取得brain,至少要有一个人!
    
//虽然不用攻击bug,所以这个人可以用来访问儿子
    
//不需要人就能获得brain,显然不行
    if(dp[u][0]>0){
        dp[u][
1]=max(dp[u][1],dp[u][0]);
        dp[u][
0]=0;
    }

}


int main(){
    
int a,b;
    
while(scanf("%d%d",&n,&m),n!=-1){
        
for(int i=1;i<=n;i++){
            scanf(
"%d%d",&bug[i],&brain[i]);
            G[i].clear();
        }

        
for(int i=1;i<n;i++){
            scanf(
"%d%d",&a,&b);
            G[a].push_back(b);
            G[b].push_back(a);
        }

        memset(vi,
0,sizeof(vi));
        dfs(
1);
        
int ans=0;
        
for(int j=1;j<=m;j++)
            ans
=max(ans,dp[1][j]);        
        printf(
"%d\n",ans);
    }

    
return 0;
}