BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个。求花费为\(m\)时最大价值。
令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值。
如果物品数量为\(1\),那就是一个树形依赖背包(选儿子必须选父亲),用DFS序优化转移:\(f[i][j]=\max(f[i+1][j-v_i]+w_i,\ f[i+sz_i][j])\)(选该节点就可以从上一个点,即子树内转移,否则只能从另一棵子树转移),复杂度\(O(nm)\)。
物品数量不为\(1\),\(\max\)的前半部分再做一次单调队列优化多重背包就行了。。复杂度也是\(O(nm)\)。(注意依赖关系,当前节点至少取一个,判一下转移位置即可)
然后如果枚举每棵子树暴力转移,复杂度是\(O(n^2m)\)的。
枚举所有连通块,可以套个点分治;或者\(dsu\ on\ tree\),保留重儿子的DP数组。(不写\(dsu\)了,但貌似常数比点分治小很多!)
然后就是\(O(nm\log n)\)了。
单调队列因为常数问题,在数据随机情况下比复杂度\(O(nm\log num)\)的二进制优化多重背包慢一些。。
(而且这题\(num\)才\(100\),数据随机不随机影响也不大了...所以这题单调队列就是慢很多很多了)
点分治:
//9068kb 10588ms(好慢QAQ懒得改)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=505,M=4005;
int n,m,Ans,W[N],V[N],num[N],Enum,H[N],nxt[N<<1],to[N<<1],Min,root,sz[N],cnt,A[N],f[N][M];
bool vis[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline void AE(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void FindRoot(int x,int fa,int tot)
{
int mx=0; sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]] && v!=fa)
FindRoot(v,x,tot), sz[x]+=sz[v], sz[v]>mx&&(mx=sz[v]);
mx=std::max(mx,tot-sz[x]);
if(mx<Min) Min=mx, root=x;
}
void MultiplePack(int *f,int *g,int val,int v,int num)
{
static int qn[M],qv[M];
const int m=::m;
for(int r=0; r<v; ++r)//余数r
for(int now=r,k=0,h=1,t=0; now<=m; now+=v,++k)
{
if(qn[h]+num<k) ++h;
if(h<=t) f[now]=std::max(f[now],qv[h]+k*val);//h<t时转移 就可以保证强制至少选一个了啊
int tmp=g[now]-k*val;//更新完f[now]再用g[now]更新队尾啊 要不有最优的会给弹掉了
while(h<=t && qv[t]<=tmp) --t;
qv[++t]=tmp, qn[t]=k;
}
}
void DP(const int cnt)
{
for(int i=cnt; i; --i)
{
int x=A[i];
for(int j=1,s=sz[x]; j<=m; ++j) f[i][j]=f[i+s][j];
MultiplePack(f[i],f[i+1],W[x],V[x],num[x]);
}
for(int i=1; i<=m; ++i) Ans=std::max(Ans,f[1][i]);
for(int i=1,s=m+1<<2; i<=cnt; ++i) memset(f[i],0,s);
}
void DFS(int x,int fa)
{
sz[x]=1, A[++cnt]=x;
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]] && v!=fa) DFS(v,x), sz[x]+=sz[v];
}
void Solve(int x)
{
vis[x]=1, cnt=0, DFS(x,0), DP(cnt);
for(int i=H[x]; i; i=nxt[i])
if(!vis[to[i]]) Min=N, FindRoot(to[i],x,sz[to[i]]), Solve(root);
}
int main()
{
for(int T=read(); T--; )
{
n=read(),m=read();
for(int i=1; i<=n; ++i) W[i]=read();
for(int i=1; i<=n; ++i) V[i]=read();
for(int i=1; i<=n; ++i) num[i]=read();
for(int i=1; i<n; ++i) AE(read(),read());
Ans=0, Min=N, FindRoot(1,1,n), Solve(root);
printf("%d\n",Ans);
Enum=0, memset(H,0,n+1<<2), memset(vis,0,n+1);//bool!
}
return 0;
}
BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)的更多相关文章
- BZOJ 4182 Shopping (点分治+树上多重背包)
题目大意:给你一颗树,你有$m$元钱,每个节点都有一种物品,价值为$w$,代价为$c$,有$d$个,如果在$u$和$v$两个城市都购买了至少一个物品,那么$u,v$路径上每个节点也都必须买至少一个物品 ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
- [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)
4182: Shopping Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 374 Solved: 130[Submit][Status][Disc ...
- BZOJ#1717:[Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+单调队列)
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的 ...
- dsu on tree:关于一类无修改询问子树可合并问题
dsu on tree:关于一类无修改询问子树可合并问题 开始学长讲课的时候听懂了但是后来忘掉了....最近又重新学了一遍 所谓\(dsu\ on\ tree\)就是处理本文标题:无修改询问子树可合并 ...
- [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)
[BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...
- CF 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths [dsu on tree 类似点分治]
D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths CF741D 题意: 一棵有根树,边上有字母a~v,求每个子树中最长的边,满 ...
- [dsu on tree]【学习笔记】
十几天前看到zyf2000发过关于这个的题目的Blog, 今天终于去学习了一下 Codeforces原文链接 dsu on tree 简介 我也不清楚dsu是什么的英文缩写... 就像是树上的启发式合 ...
- [学习笔记]Dsu On Tree
[dsu on tree][学习笔记] - Candy? - 博客园 题单: 也称:树上启发式合并 可以解决绝大部分不带修改的离线询问的子树查询问题 流程: 1.重链剖分找重儿子 2.sol:全局用桶 ...
随机推荐
- Nginx详解二:Nginx基础篇之Nginx的优点
Nginx是一个开源且高性能.可靠的HTTP中间件.代理服务 常见的HTTP服务: HTTPD--Apache基金会 IIIS--微软 GWS--Google(不对外开放) Nginx优势: 一.IO ...
- 部署MySQL5.7时的权限问题
本周部署MySQL5.7的时候遇到这样的问题,在初始化的时候,总是失败,并且报错: 2019-01-09T09:47:13.957685Z 0 [ERROR] InnoDB: Operating sy ...
- 加密算法之非对称加密RSA
一:非对称加密的由来 RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有 ...
- constructor与prototype
在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下: 我们都知道,在JS中有一个function的东西.一般人们 ...
- la4394
题解: 首先区间dp是比较好想到的 然后我感觉接下来就是乱搞... 我们会发现接下来的操作 无非就是 用一种颜色去覆盖这整个区间 然后在做 于是我用了比较暴力的做法,f[i][j][k]表示i-j这段 ...
- Java LinqCollection 仿Linq的list常用函数
目前支持find,findAll,sort,select,remove等,java不支持lamda函数,因此用接口代替 public interface Fun<T1,T2> { publ ...
- CentOS7.5安装nodejs 转
CentOS7.5安装nodejs CentOS安装NodeJS 在CentOS下安装NodeJS有以下几种方法.使用的CentOS版本为7.2.CentOS其他版本的NodeJS安装大同小异,也可以 ...
- Python_str 的内部功能介绍
float: x.as_integer_ratio():把浮点型转换成分数最简比 x.hex():返回当前值的十六进制表示 x.fromhex():将十六进制字符串转换为浮点型 float与long的 ...
- Vijos1755 靶形数独 Sudoku NOIP2009 提高组 T4 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求这个数独中所有的解法中的最大价值. 一个数独解法的价值之和为每个位置所填的数值 ...
- P1052 过河 线性dp
题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...