此题只要对于每个节点进行背包。
父亲节点的背包值为一部分取自己,一部分取儿子的和的最大值。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define MAX 101
using namespace std;
int n,m;
struct vcc{
int dp[MAX];
int val,cos;
void init(){
int i;
for(i=0;i<cos;i++){
dp[i]=0;
}
for(i=cos;i<=m;i++){
dp[i]=val;
}
}
}node[MAX];
vector<int>map[MAX];
bool hash[MAX];
void dfs(int u)
{
hash[u]=true;//哈希每个点。
node[u].init();//每个节点赋初值。
for(int i=0;i<map[u].size();i++){
int v=map[u][i];
if(hash[v])continue;
dfs(v); //dfs的神奇之处----一搜到底。
for(int j=m;j>=node[u].cos;j--){
for(int k=1;j+k<=m;k++){ //k不能从0开始,因为如果0有值的话,不能通过花费0来获得价值,这是题意不允许的。
node[u].dp[j+k]=max(node[u].dp[j+k],node[u].dp[j]+node[v].dp[k]);
} //父亲节点的状态转移。
}
}
}
void init()
{
memset(hash,false,sizeof(hash));
for(int i=0;i<=n;i++){
map[i].clear();
}
}
int main()
{
while(scanf("%d%d",&n,&m),n!=-1||m!=-1)
{
int i,j,p1,p2;
for(i=1;i<=n;i++){
scanf("%d%d",&p1,&p2);
node[i].cos=(p1+19)/20;
node[i].val=p2;
}
init();
for(i=1;i<n;i++){
scanf("%d%d",&p1,&p2);
map[p1].push_back(p2);
map[p2].push_back(p1);
}
if(m==0){
printf("0\n");
continue;
}
dfs(1);
printf("%d\n",node[1].dp[m]);
}
return 0;
}