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连 ...
随机推荐
- java的引用总结
四种引用:强弱软虚 强引用:使用强引用,在内存不足的时候垃圾处理器也不会回收他,哪怕导致程序崩溃 例如: A a=new A() 软引用:内存不足的时候会被回收(软引用可以和一个引用队列(Refere ...
- Vscode配置C++运行环境(2019/1//11更)并加入bits/stdc++.h头文件
因为重装系统,以前配置好的c++环境又没了.所以有要配置一遍. 1 下载mingw64或minw, 配置好环境变量:C://mingw64//bin; 在cmd下用g++ -v验证是否成功. 2. ...
- MySql Connector/C++8结果集处理Demo
#include <iostream> #include <exception> #include <mysqlx/xdevapi.h> using std::co ...
- 23种java设计模式之装饰者模式及动态代理
设计模式不管对于何种语言都是存在的,这里介绍的是java的模式 装饰者模式是在二次开发中应用比较多的一款模式,当然了用反射也是可以实现的,今天介绍的是装饰模式,有兴趣的朋友可以自己去了解一下反射是怎么 ...
- 获取cookie,设置cookie,删除cookie
//获取cookie export const getCookie = (name) => { var arr, reg = new RegExp("(^| )" + nam ...
- 我所用过的nginx的功能
前言 当我们提起集群时,一般所用的插件就是nginx.nginx功能如今越来越完善.第三方模块也多如牛毛,在此,总结一下不牵扯第三方模块所具有的功能. 基本功能 反向代理 负载均衡 HTTP服务器(动 ...
- mongodb的高级查询
db的帮助文档 输入:db.help(); db.AddUser(username,password[, readOnly=false]) 添加用户 db.auth(usrename,passwor ...
- symfony 数据库使用(二)
symfony可以根据数据用已经有表反向生成实体,以3.3.*为例: php bin/console doctrine:mapping:import --force AppBundle xml 从现有 ...
- centos安装zabbix(server+agent)
本文包含zabbix_server编译安装,zabbix_agent编译安装,中文字体修正 Mysql模板监控,Nginx模板监控,以及简单的web页面的使用 中文乱码的解决方案 zabbix乱码是字 ...
- Java学习笔记十二:Java中方法的重载
Java中方法的重载 什么是方法的重载呢? 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 s ...