Luogu2570 ZJOI2010 贪吃的老鼠 二分答案+最大流
题目链接:https://www.luogu.org/problemnew/show/P2570
题意概述:
好像没什么好概述的.....很简洁?
分析:
首先想到二分时间,转化成判定性问题,在一定时间内可不可以把奶酪吃完。
对于判定性问题,能不能在限制下达成吃完这个指标,可以想到最大流来解决(求限制下吃蛋糕的最大体积)。
把蛋糕的生产和过期看成两个事件,可以发现在事件发生的间隔所有老鼠的行为不会有新的选择出现,即能吃的奶酪就那些,问题的性质不发生改变。那么按照事件的发生和结束把事件间隔的时间段离散成一个个点,具体来说这一步是把老鼠拆开了。
1.每个新点向时间段内存在的每个奶酪连边,容量为inf。
2.源点向每个老鼠的点连边,容量为si*len,si表示老鼠吃奶酪的速度,len表示时间段的长度。
3.每个奶酪向汇点连边,容量为奶酪的体积pi,只要奶酪向汇点连的边满流,那么奶酪就是吃完了。
不难发现这样建图保证了每个老鼠只能在同一时间吃一块奶酪,因为我们限定了老鼠吃奶酪的最大体积,只要吃的体积满足限制,那么就一定不会同一时间吃多块奶酪,反之不合法。
但是还没有保证一块奶酪只能被一只老鼠吃。此题最妙的地方就在对这里的处理,思考一下我们对上个限制的理解,只要限制了上界,那么就一定可以在合法意义下构造出一个方案!为了构造出合法方案,我们先把所有的速度降序排序,然后进行差分,把每只老鼠的速度变成v[i]=s[i]-s[i+1]。
1.原点向每只老鼠连边,容量为len*i*v[i]。(这里的限制包含了对ii小于i的老鼠的限制)
2.每只老鼠向奶酪连边,容量为len*v[i]。
3.每块奶酪向汇点连边,容量为p[i]。
解释一下,对于每只老鼠只能吃一块奶酪的限制,我们限制了所有老鼠吃奶酪总量的上界,因此一定可以构造出合法意义下的解。同事对于一个时间段内的奶酪,所有老鼠的速度最大为s[i],两种情况达到最大值都是所有的边满流。
理解的关键:只要最后最大流满流,显然我们可以找到一种构造流量的方法,把差分之后的速度还原为原来的速度。还原流量的时候从小到大考虑。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int MAXN=;
const double eps=1e-; int K,N,M,P[MAXN],R[MAXN],D[MAXN],S[MAXN];
double sump;
struct NET{
static const int maxn=;
static const int maxm=;
static const double inf=1e9;
struct edge{ int from,to,next; double cap,flow; }E[maxm];
int n,s,t,first[maxn],np,d[maxn],gap[maxn],cur[maxn],fl[maxn];
struct event{
double p; int id;
friend bool operator < (event x,event y){
return x.p<y.p;
}
}e[]; bool vis[];
NET(){ n=np=,s=,t=; }
void add_edge(int u,int v,double cap){
E[++np]=(edge){u,v,first[u],cap,};
first[u]=np;
E[++np]=(edge){v,u,first[v],,};
first[v]=np;
}
void build(double m){
memset(first,,sizeof(first));
np=n=;
for(int i=;i<=N;i++) add_edge(++n,t,P[i]);
int cnt=;
for(int i=;i<=N;i++){
e[++cnt]=(event){R[i],i};
e[++cnt]=(event){D[i]+m,i};
}
sort(e+,e+cnt+);
memset(vis,,sizeof(vis));
int i=,k=;
vis[e[].id]^=;
while(i<cnt&&e[i+].p-e[i].p<eps) vis[e[++i].id]^=;
double last=e[i++].p;
while(i<=cnt){
for(int j=;j<=M;j++){
add_edge(s,n+k*M+j,j*S[j]*(e[i].p-last));
for(int l=;l<=N;l++)
if(vis[l]) add_edge(n+k*M+j,l,S[j]*(e[i].p-last));
}
vis[e[i].id]^=;
while(i<cnt&&e[i+].p-e[i].p<eps) vis[e[++i].id]^=;
k++,last=e[i++].p;
}
n+=k*M+;
}
void BFS(){
queue<int>q;
for(int i=;i<=n-;i++) d[i]=n;
d[s]=d[t]=n;
q.push(t); d[t]=;
while(!q.empty()){
int i=q.front(); q.pop();
for(int p=first[i];p;p=E[p].next){
int j=E[p].to,pp=(p-^)+;
if(d[j]==n&&fabs(E[pp].cap-E[pp].flow)>eps) d[j]=d[i]+,q.push(j);
}
}
}
double augment(){
int now=t; double flow=inf;
while(now!=s){
flow=min(flow,E[fl[now]].cap-E[fl[now]].flow);
now=E[fl[now]].from;
}
now=t;
while(now!=s){
E[fl[now]].flow+=flow,E[(fl[now]-^)+].flow-=flow;
now=E[fl[now]].from;
}
return flow;
}
double ISAP(){
memcpy(cur,first,sizeof(cur));
memset(gap,,sizeof(gap));
BFS();
for(int i=;i<=n-;i++) gap[d[i]]++;
gap[d[s]]++,gap[d[t]]++;
int now=s; double flow=;
while(d[s]<n){
if(now==t) flow+=augment(),now=s;
bool ok=;
for(int p=cur[now];p;p=E[p].next){
int j=E[p].to;
if(fabs(E[p].cap-E[p].flow)>eps&&d[j]+==d[now]){
ok=,fl[j]=cur[now]=p,now=j;
break;
}
}
if(!ok){
int minl=n;
for(int p=first[now];p;p=E[p].next){
int j=E[p].to;
if(fabs(E[p].cap-E[p].flow)>eps&&d[j]+<minl) minl=d[j]+;
}
if(--gap[d[now]]==) break;
gap[d[now]=minl]++;
cur[now]=first[now];
if(now!=s) now=E[fl[now]].from;
}
}
return flow;
}
}net; void data_in()
{
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++) scanf("%d%d%d",&P[i],&R[i],&D[i]);
for(int i=;i<=M;i++) scanf("%d",&S[i]);
}
bool check(double mid)
{
net.build(mid);
return fabs(net.ISAP()-sump)<eps;
}
bool cmp(int x,int y){ return x>y; }
void work()
{
sort(S+,S+M+,cmp);
for(int i=;i<M;i++) S[i]=S[i]-S[i+];
sump=;
for(int i=;i<=N;i++) sump+=P[i];
double A=,B=sump/S[M]+1.0,mid,ans;
while(B-A>=eps){
mid=(A+B)/;
if(check(mid)) ans=mid,B=mid;
else A=mid;
}
printf("%f\n",ans);
}
int main()
{
scanf("%d",&K);
for(int i=;i<=K;i++){
data_in();
work();
}
return ;
}
Luogu2570 ZJOI2010 贪吃的老鼠 二分答案+最大流的更多相关文章
- Luogu2570 [ZJOI2010]贪吃的老鼠 ---- 网络流
Luogu2570 [ZJOI2010]贪吃的老鼠 题面描述 https://www.luogu.org/problemnew/show/P2570 然后题意大概就是m只老鼠,然后吃n个奶酪,已知 ...
- Luogu P2570 [ZJOI2010]贪吃的老鼠
Luogu P2570 [ZJOI2010]贪吃的老鼠 题目描述 奶酪店里最近出现了\(m\)只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产\(n\)块奶酪,其中第\(i\)块的 ...
- luogu P2570 [ZJOI2010]贪吃的老鼠【二分+最大流】
首先考虑只满足第一个条件,二分答案,把过期时间加上mid之后的2n个时间离散,老鼠拆成每个时间的,第i个时间第j个老鼠为id[i][j],连接(s,i,p[i]),对于离散后时间(g[j-1]~g[j ...
- [ZJOI2010]贪吃的老鼠
很不错的一道网络流的题目 二分答案是显然的 首先不考虑每个饼干只能一个老鼠吃 那很显然的建图就是将时间点按照开始结束的点分成2*n-1段 然后对每一段时间建m个老鼠的点,然后s-它限流,再从它到目前可 ...
- [ZJOI2010]贪吃的老鼠 网络流
---题面--- 题解: 这是一道强题emmmm,做法非常巧妙,,,我也是看了好久大佬题解才看明白一点 首先考虑没有限制的情况,即n个老鼠可以在同一时刻吃同一块奶酪 对各个时间段拆点,连奶酪 ---& ...
- 【题解】ZJOI2010贪吃的老鼠
%%%%真的好强...看题解我都看了好久才完全明白.放一下参考的博客,谢谢神犇QAQ 1号博客 2号博客(超级赞的啦) 因为理解的过程太艰辛,所以必须记录一下这道强题:这道题目最难的两个约束就在 ...
- BZOJ 1570: [JSOI2008]Blue Mary的旅行( 二分答案 + 最大流 )
二分答案, 然后对于答案m, 把地点分成m层, 对于边(u, v), 第x层的u -> 第x+1层的v 连边. 然后第x层的u -> 第x+1层的u连边(+oo), S->第一层的1 ...
- BZOJ 1738: [Usaco2005 mar]Ombrophobic Bovines 发抖的牛( floyd + 二分答案 + 最大流 )
一道水题WA了这么多次真是.... 统考终于完 ( 挂 ) 了...可以好好写题了... 先floyd跑出各个点的最短路 , 然后二分答案 m , 再建图. 每个 farm 拆成一个 cow 点和一个 ...
- BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流
题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连 ...
随机推荐
- 数据库——MySQL——存储引擎
现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制:比如处理文本用txt类型,处理表格用excel,处理图片用png等.数据库中的表也应该有不同的类型,表的类型不同,会对 ...
- 如何配置Java环境变量
百度经验 | 百度知道 | 百度首页 | 登录 | 注册 新闻 网页 贴吧 知道 经验 音乐 图片 视频 地图 百科 文库 帮助 发布经验 首页 分类 任务 回享 商城 特色 知道 百度经验 &g ...
- ZooKeeper下载安装(Windows版本)
进入Apache ZooKeeper官方网站进行下载,https://zookeeper.apache.org/releases.html 这里我们选择zookeeper-3.4.12版本进行下载 百 ...
- 大白话解释IP多播
多播引入 比方说我是一个班主任,管着三个班,每个班30个人,每个班有自己的班长.领导让我宣传19大视 频报告,我这里有源文件.对于普通的单播我需要复制90个副本,给各个班长每人30份,然后班 长在自己 ...
- Python基础—12-面向对象(02)
面向对象 面向对象三大特点 封装:既可对数据结构进行封装,又可对处理数据的方法进行封装 继承:强调的父子类的关系 多态:不同对象调用相同的方法,会有不同的响应 类的继承 相关概念 继承:父类的属性和方 ...
- nodejs+express开发blog(1)
前言 Nodejs是一个年轻的编程框架,充满了活力和无限激情,一直都在保持着快速更新.基于Nodejs的官方Web开发库Express也在同步发展着,每年升级一个大版本,甚至对框架底层都做了大手术.在 ...
- 魔板 Magic Squares(广搜,状态转化)
题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...
- oracle优化-leading提示和ordered提示以及materialize提示
以下内容适用于oracle 10.2.0.5及其以上版本 一个查询很慢,原始SQL如下: select a.* from (select ssi.ID, 'small_station_info' TB ...
- java中的基本算法
整理一下常用的又基础的算法.由于平时的项目比较简单,很少用到算法,但工作不只是眼前的苟且,还有诗和远方. 1.链表 链表用来存储数据,由一系列的结点组成.这些结点的物理地址不一定是连续的,即可能连续, ...
- IDEA的使用方法(三)(改变字体主题)
今天正式写代码的时候发现,一开始由于破解的太随意,没有设定好主题和字体现在看的有点昏,那么接下来就发一个该如何改变IDEA的字体和主题的教程: File——>setting——>Edito ...