[JZOJ 5344] 摘果子 {树形依赖背包}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/83242003

题目

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


结题思路

这道题的模型是有依赖树形背包问题 我们把树的 d f s dfs 序建出来,对于 d f s dfs 序上每一个点,我们考虑如果自己选那么自己子树内就
可以选,否则只有在这棵子树外面才可以选。 设 f [ i ] [ j ] f[i][j] 表示 d f s dfs 序第 i i 个点及以后,费用总和为 j j 的最大价值
那么可以分第 i i 个点选或不选进行转移
选: f [ i ] [ j ] = m a x ( f [ i + 1 ] [ j w ] + v ) f[i][j]=max(f[i+1][j-w]+v)
不选: f [ i ] [ j ] = m a x ( f [ i + s i z e [ x ] ] [ j ] ) f[i][j]=max(f[i+size[x]][j]) ,其中 x x 表示 d f s dfs 序为 i i 的那个点


代码

#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; 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/83242003