思路:设dp[i][j]为以i为根节点的子树中在i点还有j个troopers的最大收益。
初值需要注意,dp[i][0]必须为0,因为你要获得i中的brain必须要放至少一个trooper。
在循环中让k从1开始取可以达到同样的效果。
转移方程:dp[u][j] = max(dp[u][j],dp[u][j-k]+dp[v][k]);
代码:
/*
* dp[u][j] = max(dp[u][j],dp[u][j-k]+dp[v][k]);
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int maxn = 105;
struct Nod{
int b,next;
void init(int b,int next){
this->b=b;this->next=next;
}
}buf[maxn<<1];
int len,E[maxn];
int n,m,wgh[maxn],val[maxn],dp[maxn][maxn];
void init(){
memset(dp,0,sizeof(dp));
memset(E,-1,sizeof(E));
len = 0;
int i,j;
for(i=1;i<=n;i++){
for(j=0;j<=m;j++)
dp[i][j] = j >= wgh[i] ? val[i] : 0;
}
}
void add_edge(int a,int b){
buf[len].init(b,E[a]);E[a]=len++;
buf[len].init(a,E[b]);E[b]=len++;
}
void dfs(int u,int pre){
//cout<<u<<"<--"<<pre<<endl;
int i,j,k,v;
for(i=E[u];i!=-1;i=buf[i].next){
v=buf[i].b;
if(v == pre) continue;
dfs(v,u);
//cout<<v<<"<--!!!"<<u<<endl;
for(j=m;j>=0;j--){
for(k=1;k<=j-wgh[u];k++)dp[u][j] = max(dp[u][j],dp[u][j-k]+dp[v][k]);
//cout<<dp[u][j]<<" ";
}
//cout<<endl;
}
}
int main(){
int i,j,a,b;
while(scanf("%d%d",&n,&m),n+m!=-2){
for(i=1;i<=n;i++){
scanf("%d%d",&wgh[i],&val[i]);
wgh[i] = wgh[i]%20 ? wgh[i]/20+1 : wgh[i]/20 ;// != 0 ? wgh[i]/20 : 1;
}
init();
for(i=1;i<n;i++){
scanf("%d%d",&a,&b);
add_edge(a,b);
}
if(m == 0){
printf("0\n");
continue;
}
dfs(1,-1);
printf("%d\n",dp[1][m]);
}
return 0;
}