题目

给定一棵大小为 \(n\) 的树,每个点代表一种物品,其具有体积、价值和数量的属性,

现在选择一个连通块,使得里面所有点都被选中且体积不超过 \(m\),问最大价值。

\(n\leq 500,m\leq 4000\)


分析

树形背包比较难维护,考虑用dfs序拍平到序列上,并且多重背包直接二进制拆分。

设 \(dp[i][j]\) 表示dfs序为 \(i\),且选择体积为 \(j\) 时能获得的最大价值。

如果不选这个点,那么 \(dp[i][j]=dp[rfn[i]][j]\),\(rfn\) 表示这个点的下一个兄弟的dfs序

如果选择这个点,那么 \(dp[i][j]=\max\{dp[i+1][j-w]+c\}\)

但有一个问题就是这样会变成01背包,考虑先用上式更新一次(强制必选一个),再用 \(dp[i][j-w]\) 更新。

就是在二进制拆分时先拆一个再正常拆,发现这样根节点强制必选,那么跑点分治,所有连通块都能被以当前根节点的情况所表示。

可以通过二进制拆分的个数来决定点的大小求带权重心,这样时间复杂度为 \(O(Tnm\log n\log m)\)


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=511; struct node{int y,next;}e[N<<1]; struct rec{int w,c;}a[N<<3];
int siz[N],big[N],as[N],L[N],R[N],w[N],c[N],ans,root,tot,v[N],dfn[N],nfd[N],rfn[N],et=1,n,m,k,dp[N][N<<3];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
void Max(int &x,int y){x=x>y?x:y;}
void dfs(int x,int fa){
siz[x]=R[x]-L[x]+1,big[x]=0;
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fa&&!v[e[i].y]){
dfs(e[i].y,x),siz[x]+=siz[e[i].y];
Max(big[x],siz[e[i].y]);
}
Max(big[x],big[0]-siz[x]);
if (big[x]<=big[root]) root=x;
}
void calc(int x,int fa){
dfn[x]=++tot,nfd[tot]=x;
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fa&&!v[e[i].y])
calc(e[i].y,x);
rfn[x]=tot+1;
}
void Dp(int x){
v[x]=1,tot=0,calc(x,0);
for (int i=0;i<=k;++i) dp[tot+1][i]=0;
for (int i=tot;i;--i){
int x=nfd[i];
for (int j=0;j<=k;++j) dp[i][j]=dp[rfn[x]][j];
for (int j=k;j>=w[x];--j)
Max(dp[i][j],dp[i+1][j-w[x]]+c[x]);
for (int o=R[x];o>L[x];--o)
for (int j=k;j>=a[o].w;--j)
Max(dp[i][j],dp[i][j-a[o].w]+a[o].c);
}
Max(ans,dp[1][k]);
for (int i=as[x];i;i=e[i].next)
if (!v[e[i].y]){
big[0]=siz[e[i].y];
dfs(e[i].y,root=0),Dp(root);
}
}
int main(){
for (int T=iut();T;--T){
n=iut(),k=iut(),ans=m=0,et=1;
for (int i=1;i<=n;++i) c[i]=iut();
for (int i=1;i<=n;++i) w[i]=iut();
for (int i=1;i<=n;++i){
int x=iut(); L[i]=R[i-1]+1;
a[++m]=(rec){w[i],c[i]},--x;
for (int t=1;x>=t;x-=t,t<<=1)
a[++m]=(rec){w[i]*t,c[i]*t};
if (x) a[++m]=(rec){w[i]*x,c[i]*x};
R[i]=m;
}
for (int i=1;i<n;++i){
int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
big[0]=m,dfs(1,root=0),Dp(root);
print(ans),putchar(10);
for (int i=1;i<=n;++i) v[i]=as[i]=0;
}
return 0;
}

#树形依赖背包,点分治#BZOJ 4182 Shopping的更多相关文章

  1. BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)

    BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...

  2. BZOJ.4910.[SDOI2017]苹果树(树形依赖背包 DP 单调队列)

    BZOJ 洛谷 \(shadowice\)已经把他的思路说的很清楚了,可以先看一下会更好理解? 这篇主要是对\(Claris\)题解的简单说明.与\(shadowice\)的做法还是有差异的(比如并没 ...

  3. bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)

    菜菜推荐的“水题”虐了我一天T T...(菜菜好强强qwq~ 显然是个分数规划题,二分答案算出p[i]-mid*s[i]之后在树上跑依赖背包,选k个最大值如果>0说明还有更优解. 第一次接触树形 ...

  4. Gym - 100502G Outing (强连通缩点+树形依赖背包)

    题目链接 问题:有n个人,最多选k个,如果选了某个人就必须选他指定的另一个人,问最多能选多少个人. 将每个人所指定的人向他连一条单向边,则每一个点都有唯一的前驱,形成的图是个基环树森林,在同一个强连通 ...

  5. RNQOJ [stupid]愚蠢的矿工(树形依赖背包)

    题意 题目链接 Sol 树形依赖背包板子题 树形依赖背包大概就是说:对于一个点,只有选了它的父亲才能选自身 把dfs序建出来,倒过来考虑 设\(f[i][j]\)表示从第\(i\)个节点往后背包体积为 ...

  6. 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包

    (上不了p站我要死了,侵权度娘背锅) Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上, ...

  7. 【LuoguP1273有线电视网】树形依赖背包

    参考论文http://wenku.baidu.com/view/8ab3daef5ef7ba0d4a733b25.html 参考一篇写的很好的博文http://www.cnblogs.com/GXZC ...

  8. BZOJ 4182 Shopping (点分治+树上多重背包)

    题目大意:给你一颗树,你有$m$元钱,每个节点都有一种物品,价值为$w$,代价为$c$,有$d$个,如果在$u$和$v$两个城市都购买了至少一个物品,那么$u,v$路径上每个节点也都必须买至少一个物品 ...

  9. AcWing 286. 选课 (树形依赖分组背包)打卡

    有依赖的背包 首先依赖的概念,就是一个东西依附与一个东西之上,我们想买附品的话必须要把主品先买下来,这个可以先做下这道题 https://www.cnblogs.com/Lis-/p/11047466 ...

  10. 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)

    The Ghost Blows Light Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The t ...

随机推荐

  1. Ubuntu常用工具和问题整理

    安装Ubuntu虚拟机时常会遇到的几个问题 1.安装时设置镜像 安装Ubuntu系统时设置国内镜像可以加快安装速度:http://mirrors.aliyun.com/ubuntu/ 参考:ubunt ...

  2. 【libGDX】加载G3DJ模型

    1 前言 ​ libGDX 提供了自己的 3D 格式模型文件,称为 G3D,包含 g3dj(Json 格式)和 g3db(Binary 格式)文件,官方介绍见 → importing-blender- ...

  3. 用Docker搭建DNS服务器

    0.准备工作 如果是全新安装的服务器,先要给root账户设置密码,命令是 sudo passwd root 然后切换到root账户 su root 上述过程屏幕输出如下 1.Docker-Compos ...

  4. 【Azure Function App】如何修改Azure函数应用的默认页面呢?

    问题描述 当在Azure中创建了一个函数应用(Function App)后,访问默认URL会得到一个默认的页面.是否有办法修改这个默认页面呢? 问题解答 在之前的博文中,介绍了修改App Servic ...

  5. 360 数科实践:JanusGraph 到 NebulaGraph 迁移

    摘要:在本文中 360 数科的周鹏详细讲解了业务从 JanusGraph 迁移到 Nebula Graph 带来的性能提升,在机器资源不到之前 JanusGraph 配置三分之一的情况下,业务性能提升 ...

  6. 3、dubbo核心用法

    https://dubbo.apache.org/zh/docs/v2.7/user/examples/preflight-check/ 1.启动时检查 在启动时检查依赖的服务是否可用 Dubbo 缺 ...

  7. git拉项目, 1.新建目录 2 git clone 地址 . (重点最后的点)

  8. vue 下 placeholder 修改颜色

    input::placeholder{ color:#585c89 !important; }

  9. pod常见的非故障及故障状态解析

    在Kubernetes中,Pod的状态可以反映其当前的生命周期状态.是否正常运行或遇到了某些状况.以下是一些Pod常见的非故障状态: Running:这是Pod最常见的非故障状态,表示Pod已经成功调 ...

  10. shell脚本中将 IFS (Internal Field Separator 内部字段分隔符)替换为换行符

    将 IFS 中的空白符(换行.制表符.空格)修改为仅包含换行 IFS 是shell中的内部变量,在使用 for var in var_list;do use $var do something don ...