剛開(kāi)始我以為是比較熟悉的樹(shù)形dp+背包,但一直wa,網(wǎng)上的代碼是非遞歸的,看到我頭暈,看了大牛的代碼后才發(fā)現(xiàn)有Trick...
       發(fā)下代碼,給有同樣問(wèn)題的人參考下

/*
    題意:給出一棵樹(shù),每個(gè)點(diǎn)有權(quán)值,要取得這個(gè)權(quán)值需要代價(jià),通過(guò)父親后才能到達(dá)兒子
    問(wèn)能量有限時(shí)獲得的最大值
    直接tree dp+背包
    注意的是,每個(gè)點(diǎn)至少要有一個(gè)人,即使沒(méi)有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; 這樣寫(xiě)會(huì)錯(cuò)
    /*
        2 1
        0 1
        0 1
        1 2
        答案是2
        上面那樣寫(xiě)答案是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];
    }

    
//一定要有這一句,占領(lǐng)父親取得brain,至少要有一個(gè)人!
    
//雖然不用攻擊bug,所以這個(gè)人可以用來(lái)訪問(wèn)兒子
    
//不需要人就能獲得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;
}