BZOJ4182 Shopping(点分治+树形dp)
点分治,每次考虑包含根的连通块,做树形多重背包即可,dfs序优化。注意题面给的di范围是假的,坑了我0.5h,心态炸了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 510
#define M 4010
#define inf 1000000000
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,w[N],c[N],d[N],p[N],t,cnt,ans;
int size[N],dfn[N],id[N],f[N][M];
bool flag[N];
struct data{int to,nxt;
}edge[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void getsize(int k,int from)
{
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to])
{
getsize(edge[i].to,k);
size[k]+=size[edge[i].to];
}
}
int findroot(int k,int from,int s)
{
int mx=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to]&&size[edge[i].to]>size[mx]) mx=edge[i].to;
if ((size[mx]<<)>s) return findroot(mx,k,s);
else return k;
}
void dfs(int k,int from)
{
dfn[k]=++cnt;size[k]=;id[cnt]=k;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to])
{
dfs(edge[i].to,k);
size[k]+=size[edge[i].to];
}
}
void solve(int k)
{
getsize(k,k);
flag[k=findroot(k,k,size[k])]=;
cnt=;dfs(k,k);
memset(f[size[k]+],,sizeof(f[size[k]+]));
//for (int i=1;i<=n;i++) cout<<size[i]<<' ';cout<<endl;
//for (int i=1;i<=n;i++) cout<<dfn[i]<<' ';cout<<endl;
//for (int i=1;i<=n;i++) cout<<id[i]<<' ';cout<<endl;
//cout<<endl;
for (int i=size[k];i;i--)
{
int x=id[i];
for (int j=;j<=m;j++)
if (j>=c[x]) f[i][j]=f[i+][j-c[x]]+w[x];
else f[i][j]=-inf;
int y=d[x];
for (int u=;u<=;u++)
if (y)
{
int z=min(y,<<u);
for (int j=m;j>=c[x]*z;j--)
f[i][j]=max(f[i][j],f[i][j-c[x]*z]+w[x]*z);
y-=z;
}
for (int j=;j<=m;j++)
f[i][j]=max(f[i][j],f[i+size[x]][j]);
}
ans=max(ans,f[][m]);
for (int i=p[k];i;i=edge[i].nxt)
if (!flag[edge[i].to]) solve(edge[i].to);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4182.in","r",stdin);
freopen("bzoj4182.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
int T=read();
while (T--)
{
n=read(),m=read();memset(p,,sizeof(p));t=ans=;
for (int i=;i<=n;i++) w[i]=read();
for (int i=;i<=n;i++) c[i]=read();
for (int i=;i<=n;i++) d[i]=read()-;
for (int i=;i<n;i++)
{
int x=read(),y=read();
addedge(x,y),addedge(y,x);
}
memset(flag,,sizeof(flag));solve();
printf("%d\n",ans);
}
return ;
}
BZOJ4182 Shopping(点分治+树形dp)的更多相关文章
- [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)
[BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...
- [BZOJ2152]聪聪可可 点分治/树形dp
2152: 聪聪可可 Time Limit: 3 Sec Memory Limit: 259 MB Submit: 3602 Solved: 1858 [Submit][Status][Discu ...
- [codeforces161D]Distance in Tree(点分治/树形dp)
题意:求树上距离为k的点对个数: 解题关键:练习一下点分治不用容斥 而直接做的做法.注意先查询,后更新. 不过这个方法有个缺陷,每次以一个新节点为根,必须memset mp数组,或许使用map会好些, ...
- BZOJ 2152 / Luogu P2634 [国家集训队]聪聪可可 (点分治/树形DP)
题意 一棵树,给定边权,求满足两点之间的路径上权值和为3的倍数的点对数量. 分析 点分治板题,对每个重心求子树下面的到根的距离模3分别为0,1,2的点的个数就行了. O(3nlogn)O(3nlogn ...
- [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP
题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...
- E. Alternating Tree 树点分治|树形DP
题意:给你一颗树,然后这颗树有n*n条路径,a->b和b->a算是一条,然后路径的权值是 vi*(-1)^(i+1) 注意是点有权值. 从上头往下考虑是点分治,从下向上考虑就是树形DP, ...
- 『You Are Given a Tree 整体分治 树形dp』
You Are Given a Tree Description A tree is an undirected graph with exactly one simple path between ...
- BZOJ4182: Shopping(点分治,树上背包)
Description 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树的形状. 第i个商店只卖第i种物品,小苗对于这种物品的喜爱度 ...
- bzoj4182 Shopping 点分治+单调队列优化多重背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...
随机推荐
- jmeter(十三)常见问题及解决方法
jmeter作为一个开源的纯Java性能测试工具,工作中极大的方便了我们进行接口.性能测试,但使用过程中也遇到了很多的问题,下面就记录一下自己遇到的问题,后续会不断更新... 1.获取日志 在使用jm ...
- GIT 分支管理:多人协作
当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin. 要查看远程库的信息,用git remote: $ git r ...
- IIS 8的第一次请求不变慢如何配置
首先需要在Window中添加Application Initialization 在IIS中配置Application Pool 在IIS配置Web Site 配置完成,如果版本在7.5,可以下载:A ...
- sql语句常用功能(null值转换为0)
COALESCE(规格,' ') 或者 COALESCE(规格,0) select * from ( ) 客户,() 物料号,p4.name 内部批次,p4.outsidename 外部批次,p1.库 ...
- SQL2005中的事务与锁定(九)-(2)- 转载
-------------------------------------------------------------------------- Author : HappyFlyStone -- ...
- HNOI2014做题笔记
HNOI2014 世界树(虚树.倍增) \(\sum M \leq 3 \times 10^5\)虚树没得跑 对于所有重要点和它们的\(LCA\)建立虚树,然后计算出每一个虚树上的点被哪个重要点控制. ...
- BZOJ1178 APIO2009 会议中心 贪心、倍增
传送门 只有第一问就比较水了 每一次贪心地选择当前可以选择的所有线段中右端点最短的,排序之后扫一遍即可. 考虑第二问.按照编号从小到大考虑每一条线段是否能够被加入.假设当前选了一个区间集合\(T\), ...
- BootStrap学习(7)_轮播图
一.轮播图 Bootstrap 轮播(Carousel)插件是一种灵活的响应式的向站点添加滑块的方式.除此之外,内容也是足够灵活的,可以是图像.内嵌框架.视频或者其他您想要放置的任何类型的内容. 如果 ...
- 验证码处理类:UnCodebase.cs + BauDuAi 读取验证码的值(并非好的解决方案)
主要功能:变灰,去噪,等提高清晰度等 代码类博客,无需多说,如下: public class UnCodebase { public Bitmap bmpobj; public UnCodebase( ...
- 【JVM.2】垃圾收集器与内存分配策略
垃圾收集器需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 在前一节中介绍了java内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈 ...