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


1
3 2
1 2 3
1 1 1
1 2 1
1 2
1 3

Sample Output


4

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

转载于:https://www.cnblogs.com/lzdhydzzh/p/8672725.html

[Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)相关推荐

  1. 单调队列优化多重背包

    就是按照 % 体积的余数来分组,每组单调队列优化. 直接上模板好了. 1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 cons ...

  2. 多重背包单调队列优化思路_多重背包之单调队列优化理论性总结

    多重背包之单调队列优化: 若用F[j]表示对容量为j的背包,处理完前i种物品后,背包内物品可达到的最大总价值,并记m = min(n, j / v).放入背包的第i种物品的数目可以是:0.1.2--, ...

  3. 多重背包单调队列优化思路_动态规划入门——多重背包与单调优化

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...

  4. 多重背包单调队列优化思路_多重背包问题

    题目描述: 无优化版本: int main(){int m, n;cin >> n >> m;for(int i = 1; i <= n; ++i){int v , w, ...

  5. 算法笔记--单调队列优化dp

    单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...

  6. 多重背包:经典DP问题( 基本/二进制优化/单调队列优化 )

    目录 基本方法 **二进制优化 *****单调队列优化 多重背包问题描述:介于01背包和完全背包问题之间,每种物品的最大选取数目都是已知的. 对于一定数量( i )的物品有一个容量为( j )的背包, ...

  7. 【学习笔记】多重背包相关优化——二进制优化/单调队列优化

    多重背包--二进制优化/单调队列优化 二进制优化 单调队列优化 代码都是 POJ1742 的,注意,那道题二进制优化会超时. 普通的多重背包式子,物品个数限制:c[i]c[i]c[i],单个物品价值 ...

  8. 单调队列优化和决策单调性优化

    前言:dp蒟蒻拼命挽救一下dp a....,会围绕三个"形如"来写...但更重要的是本质理解啊qwq A.单调队列优化: 有时状态转移方程形如f[i][j]=min{f[i-1][ ...

  9. 单调队列优化的背包问题

    对于背包问题,经典的背包九讲已经讲的很明白了,本来就不打算写这方面问题了. 但是吧. 我发现,那个最出名的九讲竟然没写队列优化的背包.... 那我必须写一下咯嘿嘿,这么好的思想. 我们回顾一下背包问题 ...

最新文章

  1. input自适应_一种Dynamic ReLU:自适应参数化ReLU(调参记录26)Cifar10~95.92%
  2. IDEA 2020.3.2控制台中文乱码分享(亲测二、下图中控制台的编码改为UTF-8)
  3. JavaScript使用技巧精萃 经典代码收藏版
  4. PPT下载下来是php,用php下载jpg,doc,ppt文件已损坏
  5. 类间关系有很多种 UML
  6. 色彩丰富的水彩纹理背景,配合排版和简单的设计元素,给任何设计带来乐趣。
  7. hnu 暑期实训之到底买不买
  8. 各厂商磁编码器对比,AS5047、AS5048、AS5600、TLE5012、MA730
  9. mongodb维护常用命令
  10. 汽车诊断协议,(K线/CAN总线、kwp2000、ISO14230、ISO1575...)转载
  11. android名字的由来构词,词根词缀词典_根据词缀查单词的词典_词根词缀 书_词根词缀记忆字典4.4.0 for android...
  12. SSM实现增删改查(IDEA)
  13. 设计模式——终结者模式
  14. Hierarchical Prosody Modeling for Non-Autoregressive Speech Synthesis
  15. 极速办公(Excel)如何方框内打勾
  16. QtWebApp的使用【在Qt中搭建HTTP服务器】(三)
  17. 【教程】在word中如何替换文字,新手请绕道!
  18. win7桌面背景变黑且不能更换壁纸
  19. pandas已知数值怎么找位置_pandas.dataframe中根据条件获取元素所在的位置方法(索引)...
  20. libgdx开发记录

热门文章

  1. static、volatile、synchronize
  2. java 生成二维码
  3. 新东方面试知识点记录
  4. 简介浏览器内核与JavaScript引擎
  5. 一个电脑同时运行 64bit 和 32bit 的eclipse 如何匹配 jdk环境
  6. windows docker 空出C盘 迁移到其他盘
  7. 原子性 atomic 类用法
  8. EasyJoyStick使用以及两种操作杆 EasyJoyStick的使用方法,简单的不能再简单 Hedgehog Team-》Easy Touch -》Add Easy Touch For C#
  9. 轮廓的查找、表达、绘制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)
  10. SpringBoot环境切换