题目链接: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 贪吃的老鼠 二分答案+最大流的更多相关文章

  1. Luogu2570 [ZJOI2010]贪吃的老鼠 ---- 网络流

    Luogu2570  [ZJOI2010]贪吃的老鼠 题面描述 https://www.luogu.org/problemnew/show/P2570 然后题意大概就是m只老鼠,然后吃n个奶酪,已知 ...

  2. Luogu P2570 [ZJOI2010]贪吃的老鼠

    Luogu P2570 [ZJOI2010]贪吃的老鼠 题目描述 奶酪店里最近出现了\(m\)只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产\(n\)块奶酪,其中第\(i\)块的 ...

  3. luogu P2570 [ZJOI2010]贪吃的老鼠【二分+最大流】

    首先考虑只满足第一个条件,二分答案,把过期时间加上mid之后的2n个时间离散,老鼠拆成每个时间的,第i个时间第j个老鼠为id[i][j],连接(s,i,p[i]),对于离散后时间(g[j-1]~g[j ...

  4. [ZJOI2010]贪吃的老鼠

    很不错的一道网络流的题目 二分答案是显然的 首先不考虑每个饼干只能一个老鼠吃 那很显然的建图就是将时间点按照开始结束的点分成2*n-1段 然后对每一段时间建m个老鼠的点,然后s-它限流,再从它到目前可 ...

  5. [ZJOI2010]贪吃的老鼠 网络流

    ---题面--- 题解: 这是一道强题emmmm,做法非常巧妙,,,我也是看了好久大佬题解才看明白一点 首先考虑没有限制的情况,即n个老鼠可以在同一时刻吃同一块奶酪 对各个时间段拆点,连奶酪 ---& ...

  6. 【题解】ZJOI2010贪吃的老鼠

    %%%%真的好强...看题解我都看了好久才完全明白.放一下参考的博客,谢谢神犇QAQ 1号博客    2号博客(超级赞的啦) 因为理解的过程太艰辛,所以必须记录一下这道强题:这道题目最难的两个约束就在 ...

  7. BZOJ 1570: [JSOI2008]Blue Mary的旅行( 二分答案 + 最大流 )

    二分答案, 然后对于答案m, 把地点分成m层, 对于边(u, v), 第x层的u -> 第x+1层的v 连边. 然后第x层的u -> 第x+1层的u连边(+oo), S->第一层的1 ...

  8. BZOJ 1738: [Usaco2005 mar]Ombrophobic Bovines 发抖的牛( floyd + 二分答案 + 最大流 )

    一道水题WA了这么多次真是.... 统考终于完 ( 挂 ) 了...可以好好写题了... 先floyd跑出各个点的最短路 , 然后二分答案 m , 再建图. 每个 farm 拆成一个 cow 点和一个 ...

  9. BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

    题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连 ...

随机推荐

  1. Vue node.js商城-购物车模块

      一.渲染购物车列表页面 新建src/views/Cart.vue获取cartList购物车列表数据就可以在页面中渲染出该用户的购物车列表数据 data(){   return {      car ...

  2. svg了解一下

    工作需求,要用svg动态生成思维导图.我的天,这是我的短板. 但是没办法,需求在这,硬着头皮上吧. 本来想偷懒,看看网上有没有现成的可以copy的,逛了一圈发现没有. 这个过程种发现了D3.Three ...

  3. 优雅的QSignleton (三) 通过属性器实现Singleton

    接下来介绍,不通过继承的方式实现单例模式.大家都出去嗨了,而我却在家码代码... 代码如下: MonoSingletonProperty.cs namespace QFramework.Example ...

  4. Linux CentOS7下安装Zookeeper-3.4.10服务(最新)

    Linux CentOS7下安装Zookeeper-3.4.10服务(最新) 2017年10月27日 01:25:26 极速-蜗牛 阅读数:1933   版权声明:本文为博主原创文章,未经博主允许不得 ...

  5. BZOJ2580: [Usaco2012 Jan]Video Game(AC自动机)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 159  Solved: 110[Submit][Status][Discuss] Descriptio ...

  6. 独木舟(51NOD 1432 )

    n个人,已知每个人体重.独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? Input 第一行包含 ...

  7. Win10家庭版卸载Mysql 8.0.13实录

    因为重度嫌弃Mysql 8.0.xxx的各种妖魔鬼怪,所以想卸载了.但是,百度了很多文章,日期也是近几个月,但是却并不适用.所以特写此文记录一下. 按照百度万金油通用第一步,就是要停止MySQL的服务 ...

  8. MySql学习笔记06

    课程回顾 一对一关联 案例1:查询每个员工的名字和主管领导的名字 select e.ename 员工姓名,m.ename 领导姓名 from emp e join emp m on e.mgr=m.e ...

  9. vertical-align垂直居中

    <div id="content"> <div id="weizi"> 锄禾日当午,<br> 汗滴禾下土.<br> ...

  10. thinkphp phpmailer邮箱验证

    thinkphp 关于phpmailer的邮箱验证 一  . 登陆自己的邮箱,例如:qq邮箱.登陆qq邮箱在账户设置中开启smtp服务: 之后回发送一个授权码 , 这个授权码先保存下来,这个授权码在后 ...