题意: 给定n和m,n为节点数,m为你拥有的士兵数,每个士兵可以消灭20个bug,每个节点有bug和values,消灭bug获得该节点的values
获得 v 节点的values 必须先消灭v父节点的values。1为入口点,即根节点。
dp【u】【j】;表示u节点 j个士兵获得的最大values。
则状态方程为: dp [ u ] [ j ] = max ( dp [ u ] [ j ] , dp [ u ] [ j - k ] + dp [ v ] [ k ] ) ;
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=110;
vector<int>V[N];
int dp[N][N];
int vis[N],n,m,bug[N],val[N];
void init()
{
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
for(int i=1;i<N;i++)
V[i].clear();;
}
void dfs(int u,int c)
{
vis[u]=1;
if(c*20<bug[u]) return ;
int tmp=(bug[u]+19)/20;
for(int i=tmp;i<=c;i++) dp[u][i]=val[u];
for(int i=0;i<(int)V[u].size();i++)
{
int v=V[u][i];
if(vis[v]) continue;
dfs(v,c-tmp);
for(int j=c;j>=tmp;j--)
{
for(int k=1;j-k>=tmp;k++)
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
}
}
}
int main()
{
//freopen("Input.txt","r",stdin);
int i;
while(~scanf("%d%d",&n,&m))
{
init();
if(n==-1&&m==-1) break;
int a,b;
for(i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
bug[i]=a;val[i]=b;
}
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
V[a].push_back(b);
V[b].push_back(a);
}
if(m==0) { puts("0");continue;} //m==0特别考虑,士兵为0,即没有人去拿values。
dfs(1,m);
printf("%d\n",dp[1][m]);
}
return 0;
}