P2570 [ZJOI2010]贪吃的老鼠
→_→唯一一篇能看得懂的题解---->这里
很容易想到二分+网络流,然而并没有什么卵用……出题人的思路太神了……
首先考虑如果一块奶酪在同一时间可以被多只老鼠吃的话,该如何建图。首先不难发现可以把时间离散化代表不同的时间段,然后把每只老鼠按对应的时间拆点。从源点向奶酪连边容量\(p[i]\),然后从奶酪向所有对应它这个时间段的拆出来的老鼠的点连边,容量为\(s[j]\times tim[i]\)(其中\(tim\)表示该段时间的长度),然后从每个老鼠的点向汇点也连这么长的边
然后发现在这种情况下不能保证每块奶酪在同一时间只会被一只老鼠吃……然后考虑一种神奇的方式:将所有老鼠按\(s\)从大到小排序,再令把\(s\)差分一下,即令\(s[i]=s[i]-s[i+1]\),而奶酪向老鼠连的边仍为\(s[j]\times tim[i]\)。那么考虑某一个时间段,某一块奶酪向该时段内这些点的流量和速度的比值分别为\(t[j]\),为了方便起见不妨设\(t[j]\)递增,那么该奶酪流出的总流量为
= \sum_{j = 2} ^ {m}(s[j] * (t[j] - t[j-1])) + s[1] * t[1]\]
然后发现,该奶酪被吃的总时间是\(t[m]\),又因为流量限制我们可以保证\(t[m]<tim[i]\),且第\(j\)只老鼠吃奶酪的总时间为\(t[j]-t[j-1]\),那么就不会存在奶酪同时被两只老鼠吃的情况了。此时老鼠向汇的边的容量要改成\(j\times s[j]\times tim[i]\),因为在差分之后这些老鼠总的能吃的奶酪应该是\(\sum j\times s[j]\)
//minamoto
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define gg(u) for(register int &i=cur[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define eps 1e-6
#define inf 1e10
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){
int res,f=1;char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=1e5+5;
struct eg{int v,nx;double w;}e[N<<1];int head[N],tot=1;
void add(int u,int v,double w){
e[++tot]={v,head[u],w},head[u]=tot;
e[++tot]={u,head[v],0},head[v]=tot;
}
int n,m,S,T,cur[N],q[N],dep[N];double L,R,mid,sum,p[N],r[N],d[N],tim[N],v[N];
inline bool cmp(double x,double y){return x>y;}
bool bfs(){
int h,t;fp(i,S,T)dep[i]=-1,cur[i]=head[i];
q[h=t=1]=S,dep[S]=0;
while(h<=t){
int u=q[h++];
go(u)if(dep[v]<0&&e[i].w>eps){
dep[v]=dep[u]+1,q[++t]=v;
if(v==T)return true;
}
}
return false;
}
double dfs(int u,double lim){
if(u==T||lim<eps)return lim;
double flow=0,f;
gg(u)if(dep[v]==dep[u]+1&&(f=dfs(v,min(lim,e[i].w)))>eps){
flow+=f,lim-=f;
e[i].w-=f,e[i^1].w+=f;
if(lim<eps)break;
}return flow;
}
inline double dinic(){double flow=0;while(bfs())flow+=dfs(S,inf);return flow;}
inline void clr(){tot=1;fp(i,S,T)head[i]=0;}
void solve(){
int cnt;double flow;S=0,T=2*n*m+n+1;
while(R-L>eps){
mid=(L+R)/2,clr();
fp(i,1,n)add(S,i,p[i]),tim[2*i-1]=r[i],tim[2*i]=d[i]+mid;
sort(tim+1,tim+2*n+1),cnt=n;
fp(i,1,m)fp(j,2,2*n)if(tim[j]-tim[j-1]>eps){
add(++cnt,T,i*v[i]*(tim[j]-tim[j-1]));
fp(k,1,n)if(r[k]-tim[j-1]<eps&&(d[k]+mid-tim[j])>-eps)
add(k,cnt,v[i]*(tim[j]-tim[j-1]));
}flow=dinic();
sum-flow<eps?R=mid:L=mid;
}printf("%lf\n",L);
}
int main(){
// freopen("testdata.in","r",stdin);
int times=read();
while(times--){
sum=0,n=read(),m=read();
fp(i,1,n)p[i]=read(),r[i]=read(),d[i]=read(),sum+=p[i];
fp(i,1,m)v[i]=read();
sort(v+1,v+1+m,cmp),R=sum/v[1]+1,L=0;
fp(i,1,m-1)v[i]-=v[i+1];solve();
}return 0;
}
P2570 [ZJOI2010]贪吃的老鼠的更多相关文章
- 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 ...
- 洛谷$P2570\ [ZJOI2010]$贪吃的老鼠 网络流+二分
正解:网络流+二分 解题报告: 传送门$QwQ$ 和上一题有点儿像,,,?$QwQ$但是比上一题要有趣很多$QwQ$ 首先把大致思路捋下?依然是.二分出每个奶酪的开始和结束时间,然后check下最大流 ...
- Luogu2570 [ZJOI2010]贪吃的老鼠 ---- 网络流
Luogu2570 [ZJOI2010]贪吃的老鼠 题面描述 https://www.luogu.org/problemnew/show/P2570 然后题意大概就是m只老鼠,然后吃n个奶酪,已知 ...
- Luogu2570 ZJOI2010 贪吃的老鼠 二分答案+最大流
题目链接:https://www.luogu.org/problemnew/show/P2570 题意概述: 好像没什么好概述的.....很简洁? 分析: 首先想到二分时间,转化成判定性问题,在一定时 ...
- [ZJOI2010]贪吃的老鼠(网络流+建图)
题目描述 奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉.第j只老鼠吃 ...
- [ZJOI2010]贪吃的老鼠
很不错的一道网络流的题目 二分答案是显然的 首先不考虑每个饼干只能一个老鼠吃 那很显然的建图就是将时间点按照开始结束的点分成2*n-1段 然后对每一段时间建m个老鼠的点,然后s-它限流,再从它到目前可 ...
- [ZJOI2010]贪吃的老鼠 网络流
---题面--- 题解: 这是一道强题emmmm,做法非常巧妙,,,我也是看了好久大佬题解才看明白一点 首先考虑没有限制的情况,即n个老鼠可以在同一时刻吃同一块奶酪 对各个时间段拆点,连奶酪 ---& ...
- 【题解】ZJOI2010贪吃的老鼠
%%%%真的好强...看题解我都看了好久才完全明白.放一下参考的博客,谢谢神犇QAQ 1号博客 2号博客(超级赞的啦) 因为理解的过程太艰辛,所以必须记录一下这道强题:这道题目最难的两个约束就在 ...
随机推荐
- mysql 之 Workbench的使用
mysql 之 Workbench的使用 (1)简介 MySQL Workbench是一款专为MySQL设计的ER/数据库建模工具.它是著名的数据库设计工具DBDesigner4的继任者.你可以用My ...
- 用jQuery向div中添加Html文本内容
前台代码: <link href="http://www.cnblogs.com/Content/themes/base/jquery-ui.css" rel="s ...
- 静态区间第k大(划分树)
POJ 2104为例[经典划分树问题] 思想: 利用快速排序思想, 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半. 查询时,在建树过程中利 ...
- 1、Java并发性和多线程-并发性和多线程介绍
以下内容转自http://ifeve.com/java-concurrency-thread/: 在过去单CPU时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行 ...
- list去掉重复元素
需求: 有list 里面含有重复元素,要求去掉重复元素: solution 1: >>> a [1, 2, 2, 1, 3, 4, 5, 6, 5] >>> set ...
- Elasticsearch学习系列之单模式下API的增删改查操作
这里我们通过Elasticsearch的marvel插件实现单模式下API的增删改查操作 索引的初始化操作 创建索引之前可以对索引进行初始化操作,比如先指定shard数量以及replicas的数量 代 ...
- Spring_2_Spring中lazy-init和scope属性
1)springTest类: public class springTest { @Test public void instanceSpring() { AbstractApplicationCon ...
- AE After Effect 如何分段渲染
如果只要第一段的话,你把要输出的那段首尾处分别按下B键和N键,这样输出时就会只输出这一段了(拖动首尾的栏目修改起始和终止的时间):如果是批量渲染的话你只要在这些不同的合成层里,每个按下ctrl+M键, ...
- 在head里的CSS link 竟然粗如今body里了?
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcGVhY2Vfb2Zfc291bA==/font/5a6L5L2T/fontsize/400/fill/I0 ...
- Oracle 远程访问配置 在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标 C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素” C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper Decimal类型截取保留N位小数向上取, Decimal类型截取保留N位小数并且不进行四舍五入操作
Oracle 远程访问配置 服务端配置 如果不想自己写,可以通过 Net Manager 来配置. 以下配置文件中的 localhost 改为 ip 地址,否则,远程不能访问. 1.网络监听配置 ...