Luogu P2570 [ZJOI2010]贪吃的老鼠

题目描述

奶酪店里最近出现了\(m\)只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉。奶酪店中一天会生产\(n\)块奶酪,其中第\(i\)块的大小为\(pi\),会在第\(ri\)秒被生产出来,并且必须在第\(di\)秒之前将它吃掉。第j只老鼠吃奶酪的速度为\(sj\),因此如果它单独吃完第i快奶酪所需的时间为\(pi/sj\)。老鼠们吃奶酪的习惯很独特,具体来说:

(1) 在任一时刻,一只老鼠最多可以吃一块奶酪;

(2) 在任一时刻,一块奶酪最多被一只老鼠吃。

由于奶酪的保质期常常很短,为了将它们全部吃掉,老鼠们需要使用一种神奇的魔法来延长奶酪的保质期。将奶酪的保质期延长\(T\)秒是指所有的奶酪的\(di\)变成\(di+T\)。同时,使用魔法的代价很高,因此老鼠们希望找到最小的T使得可以吃掉所有的奶酪。

输入格式:

输入文件的第一行包含一个整数\(K\),表示输入文件中数据的组数。

每组数据的第一行包含两个整数\(n\)和\(m\),分别表示奶酪和老鼠的数量。接下来的\(n\)行每行包含三个整数\(pi,ri,di\)。最后m行每行包含一个整数,表示\(sj。pi,ri,di,sj\)的含义如上文所述。

输出格式:

包含\(K\)行,每行包含一个实数,表示你找到的最小的\(T\)。你的答案和标准答案的绝对误差不应超过\(10−4\)。

数据范围

100%的数据中,\(1≤K≤5,1≤n,m≤30,1≤pi≤10^5, 0 ≤ri<di≤10^7,1≤sj≤10^5。\)

二分答案后跑最大流检验。

首先我们不考虑第\(2\)个限制。先把所有的时间点离散化,假设有\(k\)个时间段,然后我们将每只老鼠拆成\(k\)个点。从源点连到每个点,容量为\(s_i*len\)。第\(i\)只老鼠在这个时间段的吃奶酪上限为\(s_i*len\),所以就满足了第一个限制。每个奶酪与在\(r_i\)到\(d_i\)之间的时间段连边,然后再连向汇点,容量为\(p_i\)。

现在要考虑第\(2\)个限制。大致思路不变,只是我们要进行一些巧妙(根本想不到)的变换。将所有老鼠按\(s\)排序。第\(i\)只老鼠的新的速度为差分\(t_i=s_i-s_{i-1}\)。第\(i\)个老鼠的第\(j\)个时间点与源点之间的边的容量为\(s_i*len*(n-i+1)\)。其他不变。首先所有老鼠在某个时间段的吃奶酪数量总和不变,然后我们考虑对第\(i\)个奶酪,它在某个时间段内被吃的总量上限为\(len*\sum t_i=len*s_n\),也就是速度最快的那只老鼠。所以对于一个最大流,我们也可以构造出一个合法的情况。

代码:

#include<bits/stdc++.h>
#define N 35
#define eps 1e-6 using namespace std;
inline int Get() {
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while('0'<=ch&&ch<='9') {
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x;
}
int n,m;
struct cheese {
int p,r,d;
}ch[N];
int eat[N];
struct road {
int to,nxt;
double flow;
}s[N*N*N*10];
int h[N*N<<1],cnt;
double totflow;
void Init() {
memset(h,0,sizeof(h));
cnt=1;
}
void add(int i,int j,double f) {
s[++cnt]=(road) {j,h[i],f};h[i]=cnt;
s[++cnt]=(road) {i,h[j],0};h[j]=cnt;
}
int S,T;
queue<int>q;
int dis[N*N<<1];
bool vis[N*N<<1];
bool dinic_bfs() {
memset(dis,0x3f,sizeof(dis));
dis[S]=0;
q.push(S);
while(!q.empty()) {
int v=q.front();
q.pop();
vis[v]=0;
for(int i=h[v];i;i=s[i].nxt) {
int to=s[i].to;
if(s[i].flow>eps&&dis[to]>dis[v]+1) {
dis[to]=dis[v]+1;
if(!vis[to]) {
vis[to]=1;
q.push(to);
}
}
}
}
return dis[T]<1e9;
} double dfs(int v,double maxf) {
if(v==T) return maxf;
double ret=0;
for(int i=h[v];i;i=s[i].nxt) {
int to=s[i].to;
if(s[i].flow>eps&&dis[to]==dis[v]+1) {
double dlt=dfs(to,min(maxf,s[i].flow));
s[i].flow-=dlt;
s[i^1].flow+=dlt;
ret+=dlt;
maxf-=dlt;
if(maxf<eps) break;
}
}
return ret;
} double dinic() {
double ans=0;
while(dinic_bfs()) {
while(1) {
double tem=dfs(S,1e9);
if(tem<eps) break;
ans+=tem;
}
}
return ans;
} vector<double>tim;
bool chk(double ans) {
Init();
tim.clear();
for(int i=1;i<=n;i++) {
tim.push_back(ch[i].r);
tim.push_back(ch[i].d+ans);
}
sort(tim.begin(),tim.end());
tim.resize(unique(tim.begin(),tim.end())-tim.begin());
int tot=m*(tim.size()-1);
T=tot+n+1;
int now=0;
for(int i=1;i<=m;i++) {
for(int j=0;j<tim.size()-1;j++) {
now++;
add(S,now,min(totflow,(double)eat[i]*(tim[j+1]-tim[j])*(m-i+1)));
for(int k=1;k<=n;k++)
if(tim[j]+eps>=ch[k].r&&tim[j+1]<=ch[k].d+ans+eps) add(now,tot+k,min(totflow,(double)eat[i]*(tim[j+1]-tim[j])));
}
}
for(int i=1;i<=n;i++) add(tot+i,T,ch[i].p);
double Flow=dinic();
return fabs(Flow-totflow)<eps;
} int main() {
int cas=Get();
while(cas--) {
n=Get(),m=Get();
totflow=0;
for(int i=1;i<=n;i++) {
ch[i].p=Get();
ch[i].r=Get();
ch[i].d=Get();
totflow+=ch[i].p;
}
for(int i=1;i<=m;i++) eat[i]=Get();
sort(eat+1,eat+1+m);
double mx=eat[m];
for(int i=m;i>=1;i--) eat[i]-=eat[i-1];
double l=0,r=(double)totflow/mx+1,mid;
while(l+eps<r) {
mid=(l+r)/2.0;
if(chk(mid)) r=mid;
else l=mid+eps;
}
cout<<fixed<<setprecision(5)<<l<<"\n";
}
return 0;
}

Luogu P2570 [ZJOI2010]贪吃的老鼠的更多相关文章

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

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

  2. P2570 [ZJOI2010]贪吃的老鼠

    传送门 →_→唯一一篇能看得懂的题解---->这里 很容易想到二分+网络流,然而并没有什么卵用--出题人的思路太神了-- 首先考虑如果一块奶酪在同一时间可以被多只老鼠吃的话,该如何建图.首先不难 ...

  3. 洛谷$P2570\ [ZJOI2010]$贪吃的老鼠 网络流+二分

    正解:网络流+二分 解题报告: 传送门$QwQ$ 和上一题有点儿像,,,?$QwQ$但是比上一题要有趣很多$QwQ$ 首先把大致思路捋下?依然是.二分出每个奶酪的开始和结束时间,然后check下最大流 ...

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

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

  5. Luogu2570 ZJOI2010 贪吃的老鼠 二分答案+最大流

    题目链接:https://www.luogu.org/problemnew/show/P2570 题意概述: 好像没什么好概述的.....很简洁? 分析: 首先想到二分时间,转化成判定性问题,在一定时 ...

  6. [ZJOI2010]贪吃的老鼠(网络流+建图)

    题目描述 奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉.第j只老鼠吃 ...

  7. [ZJOI2010]贪吃的老鼠

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

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

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

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

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

随机推荐

  1. Oracle - crfclust.bdb文件太大

    今天在检查oracle rac集群时,突然才发现服务器的根目录下面占用了很多空间,照道理不应该出现这种情况,初步猜想可能是哪个日志或跟踪文件太大导致.切换到跟目录,使用du -sh *来一层一层查看到 ...

  2. Python—定时任务(APScheduler实现)

    简介                 APScheduler的全称是Advanced Python Scheduler.它是一个轻量级的基于Quartz的 Python 定时任务调度框架.APSche ...

  3. CentOS高可用集群LVS+Keepalived(DR模式)

    操作系统:CentOS6.5_x64 mini 负载均衡模式:DR(直接路由) LVS与Keepalived简述: LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是 ...

  4. ReactNative: 使用标签栏组件TabBarIOS组件

    一.简介 标签栏Tab的作用对于应用程序那是不言而喻的,它是应用程序中除了导航栏组件外的又一个核心组件,使用它可以实现页面的切换.RN提供了一个TabBarIOS组件来完成页面的切换(视图或者路由), ...

  5. 在eclipse中添加jdk源码

    window->Preferences->java->Installed JREs 点击你的jre然后点右边的Edit 找到以rt.jar结尾的jar,点击右边的Source Att ...

  6. 5面终于拿到了字节跳动offer! 鬼知道我经历了啥...

    坐标北京,某211本科毕业生,之前学校活动有去过字节跳动公司总部参观,所以一直以来就蛮想进入字节工作的,被字节的企业文化和工作氛围所影响.字节作为发展速度最快的互联网公司,旗下的很多产品的用户都比肩B ...

  7. Linux系统:Centos7下搭建ClickHouse列式存储数据库

    本文源码:GitHub·点这里 || GitEE·点这里 一.ClickHouse简介 1.基础简介 Yandex开源的数据分析的数据库,名字叫做ClickHouse,适合流式或批次入库的时序数据.C ...

  8. 图数据库 Nebula Graph 的安装部署

    Nebula Graph:一个开源的分布式图数据库.作为唯一能够存储万亿个带属性的节点和边的在线图数据库,Nebula Graph 不仅能够在高并发场景下满足毫秒级的低时延查询要求,还能够实现服务高可 ...

  9. ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)

    在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...

  10. ORM和Mybatis

    ORM框架 概述 在学习MyBatis之前,先来看看什么是ORM框架. ORM全称Object/Relation Mapping,对象/关系数据库映射,功能为完成对象的编程语言到关系数据库的映射,可以 ...