正题
题目大意
有n个东西,每个东西有价值和价格,然后要求一个价格上限,和除了第一个东西以外都有一个买这个之前必须要买的东西。
求最大价值
解题思路
我们考虑之前的树形背包
然后发现时间复杂度O(n3)O(n^3)O(n3),之后我们考虑一个方法
之前是将子节点合并起来所以时间会很久,可是我们可以将一个子节点处理好,然后直接仍给它的下一个兄弟,这样就可以O(n2)O(n^2)O(n2)解决这个问题
code
#include<cstdio>
#include<algorithm>
#define N 2010
using namespace std;
struct node{int to,next;
}a[N*2];
int n,m,dfn[N],size[N],ls[N],f[N][N],tot,cnt,v[N],p[N],x,y;
void addl(int x,int y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs(int x,int fa)//计算dfs序和子树大小
{dfn[++cnt]=x;size[x]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa) continue;dfs(y,x);size[x]+=size[y];}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d%d",&v[i],&p[i]);for(int i=1;i<n;i++){scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs(1,0);for(int i=n;i>=1;i--){int x=dfn[i];for(int j=0;j<=m;j++) f[i][j]=max(f[i+size[x]][j],0);//继承兄弟for(int j=p[x];j<=m;j++)f[i][j]=max(f[i][j],f[i+1][j-p[x]]+v[x]);//处理}printf("%d",max(0,f[1][m]));
}