4182: Shopping


Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 374  Solved: 130
[Submit][Status][Discuss]

Description


马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街。商店街有n个商店,并且它们之间的道路构成了一颗树的形状。

第i个商店只卖第i种物品,小苗对于这种物品的喜爱度是wi,物品的价格为ci,物品的库存是di。但是商店街有一项奇怪的规定:如果在商店u,v买了东西,并且有一个商店w在u到v的路径上,那么必须要在商店w买东西。小葱身上有m元钱,他想要尽量让小苗开心,所以他希望最大化小苗对买
到物品的喜爱度之和。这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为OI选手的你,你能帮帮他吗?
 

Input


输入第一行一个正整数T,表示测试数据组数。

对于每组数据,
第一行两个正整数n;m;
第二行n个非负整数w1,w2...wn;
第三行n个正整数c1,c2...cn;
第四行n个正整数d1,d2...dn;
接下来n-1行每行两个正整数u;v表示u和v之间有一条道路
 

Output


输出共T 行,每行一个整数,表示最大的喜爱度之和。
 

Sample Input



Sample Output



HINT


N<=500,M<=4000,T<=5,Wi<=4000,Di<=100

分析:


题意:两个点选了,它路径上的点必须选。求树上一个联通块的多重背包,权值最大。

题解:
 先用点分治假设重心必选,然后dfs它子树,这样每个点会做背包的次数降低到log次。
 
 然后dfs子树时列出dfs序,然后转移方程:
 

对于第二步,多重背包优化可以考虑二进制拆分总复杂度为O(Tnmlognlogm)。

也可以使用单调队列优化总复杂度O(Tnmlogn)

下面是对单调队列优化的图解:

嗯。。没了。

AC代码:


# include <cstdio>
# include <cstring>
# include <iostream>
# include <algorithm>
using namespace std;
const int N = 4e3 + ;
const int M = 5e3 + ;
int mx[N],w[N],v[N],c[N],n,m,root,head[N],dt,sz[N],sum,id[N],ed[N],ans;
int f[N][M];
bool vis[N];
struct Edge{
int to,nex;
}edge[N << ];
void AddEdge(int u,int v)
{
edge[++dt] = (Edge){v,head[u]};
head[u] = dt;
}
void find(int u,int pre)
{
mx[u] = ;sz[u] = ;
for(int i = head[u];i;i = edge[i].nex)
{
if(vis[edge[i].to] || edge[i].to == pre)continue;
find(edge[i].to,u);
sz[u] += sz[edge[i].to];
mx[u] = max(mx[u],sz[edge[i].to]);
}
mx[u] = max(mx[u],sum - sz[u]);
if(mx[u] < mx[root])root = u;
}
void dfs(int u,int pre)
{
sz[u] = ;id[++dt] = u;
for(int i = head[u];i;i = edge[i].nex)
{
if(vis[edge[i].to] || edge[i].to == pre)continue;
dfs(edge[i].to,u);
sz[u] += sz[edge[i].to];
}
ed[u] = dt;
}
int Q1[M],Q2[M];
void calc(int *g,int x)
{
int h1,h2,t1,t2,cnt,t;
for(int j = ;j < v[x];j++)
{
h1 = t1 = h2 = t2 = cnt = ;
for(int k = j;k <= m;k += v[x])
{
if(t1 - h1 == c[x] + ){
if(Q2[h2 + ] == Q1[h1 + ])++h2;
++h1;
}
t = g[k] - cnt * w[x];
Q1[++t1] = t;
while(h2 < t2 && Q2[t2] < t)--t2;
Q2[++t2] = t;
g[k] = Q2[h2 + ] + cnt * w[x];
++cnt;
}
}
}
void solve()
{
for(int i = ;i <= dt + ;i++)
for(int j = ;j <= m;j++)
f[i][j] = ;
int x,t;
for(int i = dt;i >= ;i--)
{
x = id[i];
for(int j = m;j >= v[x];j--)f[i][j] = f[i + ][j - v[x]] + w[x];
calc(f[i],x);
for(int j = m;j >= ;j--)f[i][j] = max(f[i][j],f[ed[x] + ][j]);
}
ans = max(ans,f[][m]);
}
void dfs(int u)
{
vis[u] = true;dt = ;
dfs(u,-);
solve();
for(int i = head[u];i;i = edge[i].nex)
{
if(vis[edge[i].to])continue;
root = ;sum = sz[edge[i].to];
if(sum > sz[u])sum = sum - sz[u];
find(edge[i].to,u);
dfs(root);
}
}
int main()
{
mx[] = N;
int Case;scanf("%d",&Case);
while(Case--)
{
scanf("%d %d",&n,&m);int x,y;
memset(vis,false,sizeof vis);
memset(head,,sizeof head);dt = ans = ;
for(int i = ;i <= n;i++)scanf("%d",&w[i]);
for(int i = ;i <= n;i++)scanf("%d",&v[i]);
for(int i = ;i <= n;i++)scanf("%d",&c[i]),c[i]--;
for(int i = ;i < n;i++)scanf("%d %d",&x,&y),AddEdge(x,y),AddEdge(y,x);
root = ;sum = n;find(,-);
dfs(root);
printf("%d\n",ans);
}
}
 

[Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)的更多相关文章

  1. POJ 1742 (单调队列优化多重背包+混合背包)

    (点击此处查看原题) 题意分析 给你n种不同价值的硬币,价值为val[1],val[2]...val[n],每种价值的硬币有num[1],num[2]...num[n]个,问使用这n种硬币可以凑齐[1 ...

  2. bzoj4182 Shopping 点分治+单调队列优化多重背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...

  3. POJ 1276 Cash Machine(单调队列优化多重背包)

    Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 38986   Accepted: 14186 De ...

  4. HDU 2191 - 单调队列优化多重背包

    题目: 传送门呀传送门~ Problem Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种 ...

  5. [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)

    [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...

  6. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

  7. 【POJ1276】Cash Machine(多重背包单调队列优化)

    大神博客转载http://www.cppblog.com/MatoNo1/archive/2011/07/05/150231.aspx多重背包的单调队列初中就知道了但一直没(不会)写二进制优化初中就写 ...

  8. Luogu 3423 [POI 2005]BAN-银行票据 (多重背包单调队列优化 + 方案打印)

    题意: 给出 n 种纸币的面值以及数量,求最少使用多少张纸币能凑成 M 的面额. 细节: 好像是要输出方案,看来很是头疼啊. 分析: 多重背包,裸体??? 咳咳,好吧需要低调,状态就出来了: dp [ ...

  9. poj1742 Coins(多重背包+单调队列优化)

    /* 这题卡常数.... 二进制优化或者单调队列会被卡 必须+上个特判才能过QAQ 单调队列维护之前的钱数有几个能拼出来的 循环的时候以钱数为步长 如果队列超过c[i]就说明队头的不能再用了 拿出来 ...

随机推荐

  1. 10个顶级的CSS3代码生成器

    新出来的在线工具和web应用允许开发人员快速创建网站,而无需手动一行一行地编写代码.当前,不断有新的框架和代码库涌现在前端开发这个领域里. 但是,这也让许多开发人员忘记了代码生成器以及它们在构建网站时 ...

  2. Python 学习日志9月21日

    9月21日 周四 今天是个特殊的日子吗,总感觉9月21这个日子听着怪怪的. 今天早晨看<Head First HTML and CSS>第13章节“表格和更多列表”,内容不多,看完并做了详 ...

  3. Qt 之 QApplication

    1.QApplication QApplication类管理GUI程序的控制流和主要设置,是基于QWidget的,为此特化了QGuiApplication的一些功能,处理QWidget特有的初始化和结 ...

  4. Vue项目结构梳理

    Vue项目结构图: 简单介绍目录结构 build目录是一些webpack的文件,配置参数什么的,一般不用动 config是vue项目的基本配置文件 node_modules是项目中安装的依赖模块 sr ...

  5. UITextView与UITextfield的区别

    IOS中的UITextView和UITextField都是文本输入控件并都能够调用系统键盘.本次特酷把介绍UITextView和UITextField的区别.简单来说,UITextView和UITex ...

  6. centos7 rsync+inotify软件实现集群服务的数据备份(二)

    上一篇文章记录了怎么安装rsync以及怎么使用该服务备份数据,但是在集群中需要实时备份客户发过来的相关数据,这样在使用命令或者定时任务的方式执行备份, 就满足不了整个服务的需求了. inotify是一 ...

  7. webpack 之 缓存处理

    针对 这里 的所提到的观点,如果webpack每次都生成相同名字的bundle.js,会导致问题.这里使用webpack的文件hash功能来解决,简简单单地为输出文件添加一个“[hash]”即可. / ...

  8. Mac下复制粘贴的快捷键是什么?随记

    刚从window换成Mac OS系统的用户对于一些常用的快捷键一定非常的不习惯,“mac复制粘贴快捷键是什么?”这一简单的问题相信很多刚刚从Windows平台转到Mac平台的用户会问到的问题,因为Ma ...

  9. 2018 GDCPC 省赛总结

    第二次参加省赛了,对比上年连STL都不会的acm入门者来说, 今年是接触acm的第二年. 首先要说的是今年的省赛比上年人数多了很多, 闭幕式200多支队伍坐满了整个礼堂还要站着不少人,所以今年的竞争其 ...

  10. ELK的简单安装使用

    ELK ELK是什么? Elasticsearch LogStash Kibana     1,简单的安装 我采用的是本地window环境: 下载的包如下:   首先安装的是jdk8,安装完成之后,设 ...