BZOJ 4182 Shopping (点分治+树上多重背包)
题目大意:给你一颗树,你有$m$元钱,每个节点都有一种物品,价值为$w$,代价为$c$,有$d$个,如果在$u$和$v$两个城市都购买了至少一个物品,那么$u,v$路径上每个节点也都必须买至少一个物品
单调队列数组开小了调了2h
通过这道题,本蒟蒻终于$get$到了树上带权背包的正确姿势
合并背包的代价是$O(m^{2})$的,非常不友好,而在序列上处理背包时,是不需要合并背包的,所以我们把树拍成$dfs$序
显然,树上背包需要用子节点更新父节点的信息,所以倒序枚举时间戳$i$
设$f[i][j]$表示时间戳为$i$,总代价为$j$时,所有时间戳$>=i$的节点,树上背包能得到的最大价值,令$x$表示时间戳为$i$的节点编号
如果不选节点$x$,那么它子树内的节点都不能选,为了保证$f[i]$是$i$后面所有节点构成的最优解,所以跳过$x$子树的状态,用$f[ed_{x}+1]$更新$f[i]$,$ed_{x}$表示节点$x$的出栈时间
如果选节点$x$,那么可以选$x$的子树内的节点,用$f[i+1]$更新$f[i]$
两者取最优解即可
树上带权$01$背包的时间被我们优化成了$O(nm)$
多重背包可以用单调队列优化,时间一样是$O(nm)$
而上面的$dp$方程仅适用于必须链并经过根节点的情况
所以使用点分治每次选择一个重心作为根跑$DP$
总时间$O(Tnmlogn)$
代码巨丑
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 510
#define M1 4010
#define ll long long
#define inf 233333333
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,K,T;
struct Edge{
int to[M1],nxt[M1],head[N1],cte;
void ae(int u,int v)
{cte++;to[cte]=v,nxt[cte]=head[u],head[u]=cte;}
}E; int W[N1],C[N1],D[N1];
int st[N1],ed[N1],id[N1],tot;
int sz[N1],lim[N1];
int use[N1],mi,G;
void gra(int u,int dad,int szfa)
{
int j,v,ma=szfa;
if(szfa>mi) return;
for(j=E.head[u];j;j=E.nxt[j])
{
v=E.to[j]; if(use[v]||v==dad) continue;
ma=max(ma,sz[v]);
gra(v,u,szfa+sz[u]-sz[v]);
}
if(ma<mi) mi=ma,G=u;
}
void dfs_pre(int u,int dad)
{
int j,v; sz[u]=;
st[u]=++tot; id[tot]=u;
for(j=E.head[u];j;j=E.nxt[j])
{
v=E.to[j]; if(use[v]||v==dad) continue;
lim[v]=lim[u]-C[u];
dfs_pre(v,u); sz[u]+=sz[v];
}
sz[u]++; ed[u]=tot;
}
int que[M1],hd,tl;
int f[N1][M1],ans,de;
void calc(int u)
{
int i,j,k,p,x,w,d,c;
memset(f[tot+],,sizeof(f[tot+]));
for(i=tot;i;i--)
{
x=id[i]; c=C[x]; d=D[x]; w=W[x];
memcpy(f[i],f[ed[x]+],sizeof(f[i]));
for(j=;j<c;j++)
{
hd=,tl=,que[++tl]=;
for(k=;k*c+j<=lim[x];k++)
{
while(hd<=tl&&k-que[hd]>d)
hd++;
f[i][k*c+j]=max(f[i][k*c+j],f[i+][que[hd]*c+j]+(k-que[hd])*w);
while(hd<=tl&&f[i+][k*c+j]-k*w>=f[i+][que[tl]*c+j]-que[tl]*w)
tl--;
que[++tl]=k;
}
}
}
for(j=;j<=K;j++) ans=max(ans,f[][j]);
}
void main_dfs(int u)
{
int j,v;
use[u]=; tot=,lim[u]=K;
dfs_pre(u,-);
calc(u);
for(j=E.head[u];j;j=E.nxt[j])
{
v=E.to[j]; if(use[v]) continue;
mi=inf,G=,gra(v,u,);
main_dfs(G);
}
}
void MAIN()
{
dfs_pre(,-);
mi=inf,G=,gra(,-,);
main_dfs(G);
}
void init()
{
tot=,E.cte=,ans=;
memset(use,,sizeof(use));
memset(E.head,,sizeof(E.head));
} int main()
{
freopen("t2.in","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&K);
int i,x,y,z; init();
for(i=;i<=n;i++) W[i]=gint();
for(i=;i<=n;i++) C[i]=gint();
for(i=;i<=n;i++) D[i]=gint();
for(i=;i<n;i++)
{
x=gint(), y=gint();
E.ae(x,y),E.ae(y,x);
}
MAIN();
printf("%d\n",ans);
}
return ;
}
BZOJ 4182 Shopping (点分治+树上多重背包)的更多相关文章
- [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)
[BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...
- BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...
- [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)
4182: Shopping Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 374 Solved: 130[Submit][Status][Disc ...
- bzoj4182 Shopping 点分治+单调队列优化多重背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...
- bzoj4182/luoguP6326 Shopping(点分治,树上背包)
bzoj4182/luoguP6326 Shopping(点分治,树上背包) bzoj它爆炸了. luogu 题解时间 如果直接暴力背包,转移复杂度是 $ m^{2} $ . 考虑改成点分治. 那么问 ...
- BZOJ4182: Shopping(点分治,树上背包)
Description 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树的形状. 第i个商店只卖第i种物品,小苗对于这种物品的喜爱度 ...
- BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)
BZOJ 洛谷 最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点.这样答案就是\(n-1\). 最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\( ...
- BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划
BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划 又是一道卡精度卡得我头皮发麻的题-- 题面(--蜜汁改编版) YL大哥是24OI的大哥,有一天,他想要从\(N\)个候选人中选 ...
- 【bzoj4182】Shopping 树的点分治+dfs序+背包dp
题目描述 给出一棵 $n$ 个点的树,每个点有物品重量 $w$ .体积 $c$ 和数目 $d$ .要求选出一个连通子图,使得总体积不超过背包容量 $m$ ,且总重量最大.求这个最大总重量. 输入 输入 ...
随机推荐
- HTTP 请求报文和响应报文分析和解刨!!
http请求和响应报文分析 一>http请求报文主要包括三个部分:1.请求行:2.请求头:3;请求体: 1,请求行一般包括三个部分:请求方式:请求url : http协议版本. 请求方法:大部分 ...
- j2ee消息中间件
http://blog.csdn.net/apanious/article/details/51014396
- maven tomcat 热部署
一.什么是热部署 就是在 tomcat 启动的时候进行部署 二.配置 tomcat 1.需要修改 tomcat 的 conf/tomcat-users.xml 配置文件.添加用户名.密码.权限. &l ...
- POJ 3228 Gold Transportation
Gold Transportation Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on PKU. Ori ...
- [using_microsoft_infopath_2010]Chapter 14高级话题
本章提要: 1.剖析表单逻辑 2.从多个表单中合并数据 3.重新连接XML表单到XSN模板文件 4.在repeating table中设置默认值 5.离线填写表单的权衡
- Sereja and Bottles-水题有点坑爹
CodeForces - 315A Sereja and Bottles Time Limit: 2000MS Memory Limit: 262144KB 64bit IO Format: ...
- XTU1201:模和除
题目描写叙述 两个整数x和y,满足1<=x<=a,1<=y<=b 且x%y等于x/y的x和y的对数有多少? x%y是x除以y的余数, x/y是x除以y的商,即整数除. 输入 不 ...
- HDU TIANKENG’s rice shop(模拟)
HDU 4884 TIANKENG's rice shop 题目链接 题意:模拟题.转一篇题意 思路:就模拟就可以.注意每次炒完之后就能够接单 代码: #include <cstdio> ...
- cocos2d-x之浅析Hello World
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- 【POJ 2311】 Cutting Game
[题目链接] http://poj.org/problem?id=2311 [算法] 博弈论——SG函数 [代码] #include <algorithm> #include <bi ...