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配置和启动
1.首先下载MySQl安装包,解压安装包 打开mysql下面的bin文件夹,双击如图标记的 .exe运行 2.配置Mysql (1)运行程序后点击 next (2)这里有精确配置和标准配置,根据情况 ...
- 如何使用Xcode的Targets来管理开发和生产版本的构建
如何使用Xcode的Targets来管理开发和生产版本的构建 想象一下,你已经完成了应用程序的开发和测试,现在准备提交正式版本.问题是,一些web服务的url指向了测试服务器,同时API密钥被配置用于 ...
- Struts2拦截器说明
有关于Struts2的拦截器的原理 在此共设置了两个拦截器,firstInterception.SecondInterception package struts2_inteception; publ ...
- Linux系统运维基础测试题
1 Linux运维基础测试题(第一关) 通过这段时间学习Linux基础命令,为了检测自己对Linux基础命令掌握的情况,从网上整理13到测试题,并将其整理出来供大家参考学习. 1.1 习题 ...
- PyCharm入门第一步-——创建并运行第一个Python项目
创建项目 点击Create New Project 创建项目 输入自己的项目名,点击Create创建 创建文件 右键项目名创建python文件 创建一个HelloPython文件 输入print(&q ...
- jquery添加html代码的几种方法
经常用jq来DOM添加html代码 就总结了jq里面最常用的动态添加html代码的方法 append在元素内部的尾部加上元素 prepend在元素内部的前部加上元素 after在元素外部的尾部加上元素 ...
- nodejs--http
http模块主要用到四个方法: 1.Server类 const http = require('http'); let server = new Server(); server.on('reques ...
- 2017年PHP程序员未来路在何方?(转载)
PHP 从诞生到现在已经有 20 多年历史,从 Web 时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些 ...
- python计算MD5
python有自带的MD5模块hashlib,用起来简单很多.Python Hashlib模块的使用说明 http://docs.python.org/2/library/hashlib.htmlfd ...
- thinkphp5数据库导入Excel表格
$data=$order_info; //$data 你要下载谁 就去查谁 // $data= Db::name('order_info') // ->field('consignee,tel, ...