#树形依赖背包,点分治#BZOJ 4182 Shopping
题目
给定一棵大小为 \(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的更多相关文章
- BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...
- BZOJ.4910.[SDOI2017]苹果树(树形依赖背包 DP 单调队列)
BZOJ 洛谷 \(shadowice\)已经把他的思路说的很清楚了,可以先看一下会更好理解? 这篇主要是对\(Claris\)题解的简单说明.与\(shadowice\)的做法还是有差异的(比如并没 ...
- bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)
菜菜推荐的“水题”虐了我一天T T...(菜菜好强强qwq~ 显然是个分数规划题,二分答案算出p[i]-mid*s[i]之后在树上跑依赖背包,选k个最大值如果>0说明还有更优解. 第一次接触树形 ...
- Gym - 100502G Outing (强连通缩点+树形依赖背包)
题目链接 问题:有n个人,最多选k个,如果选了某个人就必须选他指定的另一个人,问最多能选多少个人. 将每个人所指定的人向他连一条单向边,则每一个点都有唯一的前驱,形成的图是个基环树森林,在同一个强连通 ...
- RNQOJ [stupid]愚蠢的矿工(树形依赖背包)
题意 题目链接 Sol 树形依赖背包板子题 树形依赖背包大概就是说:对于一个点,只有选了它的父亲才能选自身 把dfs序建出来,倒过来考虑 设\(f[i][j]\)表示从第\(i\)个节点往后背包体积为 ...
- 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包
(上不了p站我要死了,侵权度娘背锅) Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上, ...
- 【LuoguP1273有线电视网】树形依赖背包
参考论文http://wenku.baidu.com/view/8ab3daef5ef7ba0d4a733b25.html 参考一篇写的很好的博文http://www.cnblogs.com/GXZC ...
- BZOJ 4182 Shopping (点分治+树上多重背包)
题目大意:给你一颗树,你有$m$元钱,每个节点都有一种物品,价值为$w$,代价为$c$,有$d$个,如果在$u$和$v$两个城市都购买了至少一个物品,那么$u,v$路径上每个节点也都必须买至少一个物品 ...
- AcWing 286. 选课 (树形依赖分组背包)打卡
有依赖的背包 首先依赖的概念,就是一个东西依附与一个东西之上,我们想买附品的话必须要把主品先买下来,这个可以先做下这道题 https://www.cnblogs.com/Lis-/p/11047466 ...
- 【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 ...
随机推荐
- Docker实践之06-访问仓库
目录 什么是仓库 一.Docker Hub 注册 登录 拉取镜像 推送镜像 自动创建 二.私有仓库 Docker Registry 安装Docker Registry 在私有仓库上传/搜索/下载镜像 ...
- 遭遇DDOS攻击忍气吞声?立刻报警!首都网警重拳出击,犯罪分子无所遁形
公元2024年2月24日18时许,笔者的个人网站突然遭遇不明身份者的DDOS攻击,且攻击流量已超过阿里云DDos基础防护的黑洞阈值,服务器的所有公网访问已被屏蔽,由于之前早已通过Nginx屏蔽了所有国 ...
- 【算法day6】哈希表、有序表、链表(反转单链表)
哈希表的简单介绍 1)哈希表在使用层面上可以理解为一种集合结构 2)如果只有key,没有伴随数据value,可以使用HashSet结构(C++中叫UnOrderedSet) 3)如果既有key,又有伴 ...
- [Node] nvm 安装 node 和 npm
Node JS 安装 安装 node version manager (nvm) Windows: https://github.com/coreybutler/nvm-windows/release ...
- 【Azure App Service for Linux】Linux Web App如何安装系统未安装的包
问题描述 Linux Web App中如何安装系统默认未安装的包,如何来执行如 apt install XXX命令呢?现在遇见的问题时,通过Azure App Service门户中的SSH登录后,执行 ...
- 一文了解 NebulaGraph 上的 Spark 项目
本文首发于 Nebula Graph Community 公众号 最近我试着搭建了方便大家一键试玩的 Nebula Graph 中的 Spark 相关的项目,今天就把它们整理成文分享给大家.而且,我趟 ...
- 调试 Docker 容器内部进程
首发于官方博客:https://nebula-graph.com.cn/posts/debug-nebula-graph-processes-docker/ 摘要:本文以 Nebula Graph 进 ...
- 快速复习JDBC(超详细)
第一章 JDBC概述 之前我们学习了JavaSE,编写了Java程序,数据保存在变量.数组.集合等中,无法持久化,后来学习了IO流可以将数据写入文件,但不方便管理数据以及维护数据的关系: 后来我们学 ...
- 全面解析 Redis 持久化:RDB、AOF与混合持久化
前言: 每次你在游戏中看到玩家排行榜,或者在音乐应用中浏览热门歌单,有没有想过这个排行榜是如何做到实时更新的?当然,依靠 Redis 即可做到. 在技术领域,我们经常听到「键值存储」 这个词.但在 R ...
- 使用 Docker 部署 Answer 问答平台
1)介绍 GitHub:https://github.com/apache/incubator-answer Answer 问答社区是在线平台,让用户提出问题并获得回答.用户可以发布问题并得到其他用户 ...