题意:

有n个洞,连接像一棵树,每个包含一定数量的怪和价值,给你m个士兵,每个士兵能打20个怪,杀完一个洞的怪可得该洞的价值才可继续打相连的下面的洞(每个士兵只能打一个洞),求获得的最大价值。

分析:把士兵数看做容量,就是背包问题,dp[i][j]以i为根节点子树士兵数j时获得的最大价值(根节点有一定的士兵,要先打通根节点)1是根节点

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
const ll INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod = ;
vector<int>e[];
int used[],dp[][],p[],b[];
int n,m;
void dfs(int root){
int tmp=(b[root]+)/;//打通根节点需士兵数
for(int k=tmp;k<=m;++k)
dp[root][k]=p[root];
used[root]=;
for(int i=;i<e[root].size();++i){
int son=e[root][i];
if(used[son])continue;
dfs(son);
for(int j=m;j>=tmp;--j)
for(int l=;l<=j-tmp;++l)
dp[root][j]=max(dp[root][j],dp[root][j-l]+dp[son][l]);
}
}
int main()
{
while(~scanf("%d%d",&n,&m)){
if(n==-&&m==-)break;
for(int i=;i<=n;++i){
scanf("%d%d",&b[i],&p[i]);
e[i].clear();
}
memset(dp,,sizeof(dp));
memset(used,,sizeof(used));
int u,v;
for(int i=;i<n-;++i){
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
if(m==)printf("0\n");
else{
dfs();
printf("%d\n",dp[][m]);
}
}
return ;
}
05-08 15:30