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\) 为根的子树 ...
随机推荐
- Android学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储
前面一讲介绍了数据持久化技术的前两种:文件存储.SharedPreferences存储.下面介绍第三种技术:SQLite数据库存储 一.SQLite数据库存储 SQLite数据库是一款轻量级的关系型数 ...
- MySQL(十四)管理维护及性能优化
关于MySQL的学习,<MySQL必知必会>这本书呢,看完已经两个月了,一直被工作以及生活的一些琐事拖着,趁着今晚有空闲,就整理完了最后的几章学习笔记,接下来的学习计划呢, 应该是pyth ...
- 开放的dae模型
从网上看到了这段代码,就Copy过来了. 其实面对dae这种开放的模型格式,我们可以做很多事情,就像通常的XML文件一样. //------------------------------------ ...
- Linux下安装解压版(tar.gz)MySQL5.7
最近尝试在Linux中安装了解压版MySQL,期间查阅了许多博客.很多博客看得我很懵逼,因此记录下自己的安装过程,方便后续查阅. 环境说明:CentOs7.2 一.清理 ...
- [Spark][python]RDD的collect 作用是什么?
[Spark][Python]sortByKey 例子的继续 RDD的collect() 作用是什么? “[Spark][Python]sortByKey 例子”的继续 In [20]: mydata ...
- Stencil 基础
Stencil 一个轻量化,渐进式编译器,注意,不是框架. 使用 TypeScript 进行所有操作,这是一个门槛,有一定技术门槛要求. PS:个人强烈推荐所有的前端同学都学习,或至少了解这个超集语言 ...
- ExtJS框架基础:事件模型及其常用功能
前言 工作中用ExtJS有一段时间了,Ext丰富的UI组件大大的提高了开发B/S应用的效率.虽然近期工作中天天都用到ExtJS,但很少对ExtJS框架原理性的东西进行过深入学习,这两天花了些时间学习了 ...
- mysql操作命令梳理(1)-索引
1.创建索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIMARY KE ...
- JavaScript之命名空间模式
前言 命名空间可以被认为是唯一标识符下代码的逻辑分组.为什么会出现命名空间这一概念呢?因为可用的单词数太少,并且不同的人写的程序不可能所有的变量都没有重名现象.在JavaScript中,命名空间可以帮 ...
- 读书笔记(chapter4)
进程调度 4.1多任务 1.多任务系统可以划分为:非抢占式多任务和抢占式多任务: (在此模式下,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行机会,这个动作叫抢占: 时间片实际上 ...