版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/83242003
题目
结题思路
这道题的模型是有依赖树形背包问题 我们把树的 序建出来,对于 序上每一个点,我们考虑如果自己选那么自己子树内就
可以选,否则只有在这棵子树外面才可以选。 设 表示 序第 个点及以后,费用总和为 的最大价值
那么可以分第 个点选或不选进行转移
选:
不选: ,其中 表示 序为 的那个点
代码
#include<cstdio>
#define rr register
using namespace std;
struct node{int y,next;}a[20001];
int num,ans,len,n,m,v[20001],p[20001],last[20001],d[20001],size[20001],f[5001][5001];
inline int maxx(int x,int y) {return x>y?x:y;}
void add(int x,int y)
{
a[++len]=(node){y,last[x]}; last[x]=len;
a[++len]=(node){x,last[y]}; last[y]=len;
}
inline int read()
{
int p=0,f=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
while (c>='0'&&c<='9') p=(p<<3)+(p<<1)+c-'0',c=getchar();
return p*f;
}
void dfs(int x,int fa)
{
d[++num]=x;
for (rr int i=last[x];i;i=a[i].next){
int y=a[i].y;
if (y==fa) continue;
dfs(y,x);
size[x]+=size[y];
}
size[x]++; return;
}
int main()
{
n=read(),m=read();
for (rr int i=1;i<=n;i++) v[i]=read(),p[i]=read();
for (rr int i=1;i<n;i++) add(read(),read());
dfs(1,0);
for (rr int i=n;i>=1;i--)
for (rr int j=m;j>=0;j--)
{
if (j-p[d[i]]>0) f[i][j]=maxx(f[i][j],f[i+1][j-p[d[i]]]+v[d[i]]);
f[i][j]=maxx(f[i][j],f[i+size[d[i]]][j]);
}
for (rr int i=0;i<=m;i++)
ans=maxx(ans,f[1][i]);
printf("%d",ans);
return 0;
}