BZOJ4182 : Shopping
最后选择的一定是树上的一个连通块,考虑树分治,每次只需考虑重心必选的情况,这就变成了以重心为根的树形依赖多重背包问题。
设f[x][j]表示从根节点到x这条路径及其左边的所有节点,以及以x为根的子树的所有节点中,容量为j的背包选取物品所能得到的最大价值。
对于x的儿子y,将f[y]初始值设为f[x]中强制放入一个y,然后将d[y]-1二进制拆分后放入f[y]中,最后将f[x][j]与f[y][j]取个最优解即可。
时间复杂度O(nmlognlogd)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include<cstdio> #define N 510 int T,n,m,i,x,y,ed,g[N],nxt[N<<1],v[N<<1],ok[N<<1],son[N],f[N],size,now; int a[N],b[N],c[N],dp[N][4010],ans; inline void add( int x, int y){v[++ed]=y,nxt[ed]=g[x],ok[ed]=1,g[x]=ed;} inline void up( int &a, int b){ if (a<b)a=b;} void findroot( int x, int y){ son[x]=1;f[x]=0; for ( int i=g[x];i;i=nxt[i]) if (ok[i]&&v[i]!=y){ findroot(v[i],x); son[x]+=son[v[i]]; if (son[v[i]]>f[x])f[x]=son[v[i]]; } if (size-son[x]>f[x])f[x]=size-son[x]; if (f[x]<f[now])now=x; } void dfs( int x, int y, int m){ if (m<=0) return ; int i,j,k,V,W; for (j=c[x],i=0;j;i++) if ((1<<i)<=j){ for (V=a[x]<<i,W=b[x]<<i,k=m;k>=W;k--)up(dp[x][k],dp[x][k-W]+V); j-=1<<i; } else { for (V=a[x]*j,W=b[x]*j,k=m;k>=W;k--)up(dp[x][k],dp[x][k-W]+V); break ; } for (i=g[x];i;i=nxt[i]) if (ok[i]&&v[i]!=y){ for (j=0;j<=m-b[v[i]];j++)dp[v[i]][j]=dp[x][j]+a[v[i]]; dfs(v[i],x,m-b[v[i]]); for (j=b[v[i]];j<=m;j++)up(dp[x][j],dp[v[i]][j-b[v[i]]]); } } void solve( int x){ int i; for (i=0;i<=m-b[x];i++)dp[x][i]=a[x]; for (dfs(x,i=0,m-b[x]);i<=m-b[x];i++)up(ans,dp[x][i]); for (i=g[x];i;i=nxt[i]) if (ok[i])ok[i^1]=0,f[0]=size=son[v[i]],findroot(v[i],now=0),solve(now); } int main(){ for ( scanf ( "%d" ,&T);T--; printf ( "%d\n" ,ans)){ scanf ( "%d%d" ,&n,&m),ans=0,ed=1; for (i=1;i<=n;i++) scanf ( "%d" ,&a[i]),g[i]=0; for (i=1;i<=n;i++) scanf ( "%d" ,&b[i]); for (i=1;i<=n;i++) scanf ( "%d" ,&c[i]),c[i]--; for (i=1;i<n;i++) scanf ( "%d%d" ,&x,&y),add(x,y),add(y,x); f[0]=size=n,findroot(1,now=0),solve(now); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· 千万级的大表,如何做性能调优?
· .NET周刊【1月第1期 2025-01-05】