[ZJOI2010] 贪吃的老鼠(二分+差分+神仙建图网络流)

problem

luogu-P2570

solution

卧槽网络流尼玛神题

首先这个最小延长时间 TTT ,套路地考虑二分,将问题转化为判定性问题。

其次 n,mn,mn,m 和奶酪存在时间 [l,r][l,r][l,r] 的量级差很大,我们肯定会猜想一段时间内选择吃奶酪的老鼠是一样,套路地考虑离散化。

nnn 个奶酪的出现、消失时间放进时间轴 ti[]ti[]ti[] 中。

有序化,将时间轴割裂成若干段不相交且并集为全集的的小区间,一段时间一段时间地考虑。

像这种贪心贪不动,dppdp\ pdp p 不动的题目,我们就可以往网络流上靠了 。

其实是感觉是个网络流那它多半就是网络流。

现在就当大家已经想(猜)到这是道网络流了。

这道题问题就在于如何建立一个和原问题等价的网络流。

满足:任一时刻,一只老鼠最多吃一块奶酪,一块奶酪最多被一只老鼠吃。

因为网络流是同时多路径流,所以我们很难在网络流上面直观理解一对一。


本版块是对建图的描述。

刚开始,很容易想到。s,ts,ts,t 源汇点,1∼n1\sim n1n 的奶酪,源点 sss 分别与这 nnn 块奶酪连边,容量为对应奶酪的大小 ppp

然后后面就开始 尼玛 神起来了。

  • 首先要将老鼠按吃的 速度从大到小 排序,最后面插个速度 000,再 差分 一下,得到新的速度序列 {v}\{v\}{v}

    e.g.:5429→95420→4122\text{e.g.}:5\ 4\ 2\ 9\rightarrow 9\ 5\ 4\ 2\ 0\rightarrow 4\ 1\ 2\ 2e.g.:5 4 2 99 5 4 2 04 1 2 2

    后面建图部分的第 iii 个老鼠点若未明确指出原老鼠 / 差分老鼠,则均指已经差分后的第 iii 个老鼠点。

差分过后,按划分的每个时间段重复以下的操作:

假设这个时间段 jjj 的长度为 time=ti[j+1]−ti[j]time=ti[j+1]-ti[j]time=ti[j+1]ti[j]

  • 枚举 1∼m1\sim m1m 老鼠,给其一个新编号 tot++tot++tot++,与汇点连边。

    iii 个老鼠连边容量为 vi⋅i⋅timev_i·i·\text{time}viitime

    你肯定会疑惑这个容量太奇怪了。但先别着急。

    看图:在这里插入图片描述

    vi⋅i:v_i·i:vii: 差分值乘上它的差分数组内的编号。

    我们观察得到,假设差分数组为 ddd,原数组为 ooo,则有 ∑di⋅i=∑oi\sum d_i·i=\sum o_idii=oi

    那么乘上 timetimetime 就是这个老鼠点在这个时间段能吃的奶酪限制。

    这个差分相当于将原老鼠切成了若干块,按相同块分类合并。

    这个在差分数组内的编号 iii 意思就是有 iii 只原老鼠能划分出这个 v[i]v[i]v[i] 块,统称一只差分老鼠。

  • 枚举 1∼n1\sim n1n 奶酪,对完全在这个时间段出现的奶酪继续操作:

    与每个老鼠连边,容量 vi⋅timev_i·timevitime

    表示一只老鼠最多在一块奶酪上付出的努力。

    看图:在这里插入图片描述

你可以将不同颜色的蓝线当作坐标轴的 x,yx,yx,y 基准轴,然后划分出每个速度老鼠小方格,一个小方格一个小方格地分配。

从上往下从左往右第 (x,y)(x,y)(x,y) 的方格可以理解为该时间段会有第 yyy 只原老鼠吃掉第 xxx 个奶酪的 vy⋅timev_y·timevytime 大小的部分。

每个奶酪会分配到某些行中的一个小方格,然后拼凑出来,相当于是吃掉了这个奶酪的一部分。


本板块是证明此种 奇怪神奇但是对的 网络流建图方式不会出现不合法的情况,即不存在某一时刻一只老鼠同时吃多个奶酪 / 一个奶酪同时被多只老鼠吃。

PS:本版块若未强调差分老鼠,则均指是原老鼠。

  • 先证明不存在一只老鼠同时吃多个奶酪的情况。

    假设排序后第 kkk 只老鼠在该时间段吃了 xxx 块奶酪,第 iii 块奶酪吃了时间 tit_iti

    如果 (∑ti)>time(\sum t_i)> time(ti)>time,则表示存在一只老鼠同时吃多个奶酪(不合法)。

    首先第 kkk 个差分老鼠至少产生的流量都是 (∑ti)⋅vk(\sum t_i)·v_k(ti)vk,而容量为 vk⋅k⋅timev_k·k·timevkktime

    此时有两种情况:

    • 有速度更快的老鼠能够帮吃超额部分(引起老鼠必须同时吃奶酪的部分),那么就可以分担。

      就不会存在 (∑ti)>time(\sum t_i)>time(ti)>time。(也就是说看似不合法的流法可以通过调整变成合法流法)

    • 不能帮吃完所有超额部分。那么这些更快的老鼠肯定是吃过了,也就是它们在这个时间段每时每刻都在吃。

      在差分上会体现成前 k−1k-1k1 个差分老鼠对 kkk 差分老鼠造成流量负担,加上原本流量,(∑ti)⋅vk+(k−1)⋅vk⋅time=k⋅vk⋅time+vk⋅((∑ti′)−time)>k⋅vk⋅time(\sum t_i)·v_k+(k-1)·v_k·time=k·v_k·time+v_k·\big((\sum t_i')-time\big)>k·v_k·time(ti)vk+(k1)vktime=kvktime+vk((ti)time)>kvktime,即流量大于容量,显然不可能,所以在网络流图上不可能跑成这样。(如果调整不了那么一开始就不可能跑成这种情况)

  • 再证明不存在一个 iii 奶酪同时被多只老鼠吃的情况。

    假设有 xxx 只老鼠吃了该奶酪,吃了时间 tit_iti

    如果 (∑ti)>tim(\sum t_i)>tim(ti)>tim 则表示存在一个奶酪同时被多只老鼠吃。

    由于排名靠前的老鼠会对排名靠后的老鼠造成影响。即吃了同一个奶酪的 排名最后面的 老鼠流量为 (∑ti)⋅vk>ti⋅vk(\sum t_i)·v_k>t_i·v_k(ti)vk>tivk(奶酪向每个差分老鼠的连边容量)。

    也不存在跑出这种情况的可能。


在建图板块,是从差分到原来;而在证明板块,是从原来到差分。可多思考一下。

因为这个建图是差分后的建图,所以如果要输出方案(即还原每只老鼠吃的时间)很有可能遇到差分还原后某只老鼠的时间是负数。
还原方法就是第一只差分老鼠的流量 /v/v/v 就是时间,然后把编号比它大的所有差分老鼠减去这个老鼠造成的流量贡献,以此类推。
网络流的流法很多种,我们只是知道最后流满没有。所以有可能某种流法看上去是不对的,但是它一定可以被调整成一种合法流法(优先满足编号小的差分老鼠)。
所以考察输出方案的话就显得不可做了。

code

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 100000
#define maxm 500000
#define eps 1e-6
#define inf 1e9int s, t, cnt, T, n, m;
int head[maxn], cur[maxn], dep[maxn];
struct edge { int to, nxt; double flow; }E[maxm];
namespace NetworkFlow {queue < int > q;void init() { s = 0, t = n * m * 2 + 1, cnt = -1, memset( head, -1, sizeof( head ) ); }void addedge( int u, int v, double w ) {E[++ cnt] = { v, head[u], w }, head[u] = cnt;E[++ cnt] = { u, head[v], 0 }, head[v] = cnt;}bool bfs() {memset( dep, 0, sizeof( dep ) );memcpy( cur, head, sizeof( head ) );dep[s] = 1; q.push( s );while( ! q.empty() ) {int u = q.front(); q.pop();for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( ! dep[v] and E[i].flow > eps ) {dep[v] = dep[u] + 1;q.push( v );}}}return dep[t];}double dfs( int u, double cap ) {if( u == t or cap < eps ) return cap;double flow = 0;for( int i = cur[u];~ i;i = E[i].nxt ) {int v = E[i].to; cur[u] = i;if( dep[v] == dep[u] + 1 ) {double w = dfs( v, min( cap, E[i].flow ) );if( w < eps ) continue;E[i ^ 1].flow += w;E[i].flow -= w;flow += w;cap -= w;if( cap < eps ) break;}}return flow;}double dinic() {double ans = 0;while( bfs() ) ans += dfs( s, inf );return ans;}
}struct node { double p, l, r; }c[maxn];
double v[maxn], ti[maxn];
double sum;
bool check( double delta ) {NetworkFlow :: init();for( int i = 1;i <= n;i ++ ) {NetworkFlow :: addedge( s, i, c[i].p );ti[i] = c[i].l, ti[i + n] = c[i].r + delta;}sort( ti + 1, ti + (n << 1 | 1) );int tot = n;for( int i = 1;i <= m;i ++ )for( int j = 1;j < (n << 1);j ++ ) {if( ti[j + 1] - ti[j] < eps ) continue;tot ++, NetworkFlow :: addedge( tot, t, ( ti[j + 1] - ti[j] ) * v[i] * i );for( int k = 1;k <= n;k ++ )if( c[k].l <= ti[j] and  ti[j + 1] <= delta + c[k].r )NetworkFlow :: addedge( k, tot, ( ti[j + 1] - ti[j] ) * v[i] );}return sum - NetworkFlow :: dinic() < eps; 
}signed main() { scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &n, &m );for( int i = 1;i <= n;i ++ ) scanf( "%lf %lf %lf", &c[i].p, &c[i].l, &c[i].r );sum = 0; for( int i = 1;i <= n;i ++ ) sum += c[i].p;for( int i = 1;i <= m;i ++ ) scanf( "%lf", &v[i] );sort( v + 1, v + m + 1, []( int x, int y ) { return x > y; } ); for( int i = 1;i < m;i ++ ) v[i] = v[i] - v[i + 1];double l = 0, r = 5e7, ans;while( l + eps < r ) {double mid = ( l + r ) / 2;if( check( mid ) ) ans = mid, r = mid;else l = mid;}printf( "%.4f\n", ans );}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cf1553D. Backspace

cf1553D. Backspace 题意&#xff1a; 有一个字符串A,现在将其一个一个输入至B中,在输入一个字符时,如果按下backspace,那么这个字符不会被键入,而且如果B不为空,则前一位(B.back)也会被删除,现给出一个字符串C,问能否得到一个B&#xff0c;使得BC 题解&#xff1a; 为了通…

基于IdentityServer的系统对接微信公众号

业务需求公司有两个业务系统&#xff0c;A和B&#xff0c;AB用户之间属于多对一的关系&#xff0c;数据库里面也就是两张表&#xff0c;A表有个外键指向B。现在需要实现以下几个功能。A用户扫描B的二维码&#xff0c;填写相关的注册信息&#xff0c;注册完成之后自动属于B。也就…

[TJOI2012] 旅游(树的直径)

problem 写的什么jb题意&#xff01;这个语文水平。。。。 洛谷的一堆题解看下来也没懂他们懂得题目大意&#xff0c;真是给我蚌埠住了 luogu评测链接 一句话题意&#xff1a;给定一个三角剖分&#xff0c;求任意两顶点穿过的最多三角形个数&#xff08;只经过某三角形顶点…

Python知识(4/20):Python条件判断

任何一个复杂的系统都是由三种基本结构组成&#xff1a;顺序结构、分支结构、循环结构。其中 顺序结构最简单&#xff0c;程序从上到下依次执行&#xff0c;就如同生活中一条笔直的大马路&#xff0c;一路畅行无阻&#xff1b; 分支结构是指当程序执行到某步时&#xff0c;需根…

Ocelot Api网关教程(9)- QoS

本文介绍Ocelot中的QoS(Quality of Service)&#xff0c;其使用了Polly对超时等请求下游失败等情况进行熔断。1、添加Nuget包添加 Ocelot.Provider.Polly 到OcelotGetway项目中2、修改 Startup.ConfigureServices 如下来添加Polly&#xff1a;services .AddOcelot(new Confi…

cf1553F. Pairwise Modulo

cf1553F. Pairwise Modulo 题意&#xff1a; 给你一个数组a&#xff0c;a由n个不同的数组成,让你求出对应的数组p 数组p的定义为&#xff1a; pk∑1≤i,j≤kaimodajp_{k}\sum_{1\leq i,j\leq k}a_{i} \mod a_{j}pk​∑1≤i,j≤k​ai​modaj​ 题解&#xff1a; 官方题解 首…

[ZJOI2011]营救皮卡丘(费用流 + 最短路)

problem luogu-P4542 solution 刚开始就直观感觉 dpdpdp 不动&#xff0c;却有个看似“理所当然”的贪心&#xff1a;每次跑 kkk 个人所在点到扩展据点的最短距离&#xff0c;然后让最近的人去破环那个据点。 啪啪敲完后小样例&#xff08;实在太水&#xff09;就过了&…

Deltix Round, Spring 2021 (open for everyone, rated, Div. 1 + Div. 2)

Deltix Round, Spring 2021 (open for everyone, rated, Div. 1 Div. 2) 题号题目知识点AGame of LifeBLord of the ValuesCCompression and ExpansionDLove-HateECrypto LightsFFavorite GameGTry BookingHHopping Around the Array

Abp框架准备加入.NET Foundation

Abp团队正准备尝试将Abp项目加入.NET Foundation!既然申请了,必然有很大的自信能够成功,请大家等待好消息!Abp中文网会第一时间跟进.点击阅读原文查看最新进展.

[ZJOI2011] 道馆之战(树链剖分)

problem luogu-P4679 理解清楚题意又是一个世纪的更迭了 给定一个树&#xff0c;每个节点位置上实际放了两个节点。 然后若干次修改和查询。... 能走&#xff0c;#\## 不能走。 询问 u→vu\rightarrow vu→v 的简单路径上最长能走的距离。&#xff08;是强制从 uuu 开始&a…

[NOI2008] 志愿者招募(线性规划-对偶问题-费用流)

problem luogu-P3980 solution 志愿者连续工作 [si,ti][s_i,t_i][si​,ti​] 天&#xff0c;我们可以提炼出网络流二十四题中《最长k可重区间集问题》的模型。 同样地&#xff0c;把 1∼n1\sim n1∼n 天抽象成一条 1∼n11\sim n11∼n1 个点的链条。 源点 s→1s\rightarrow…

互达的集合(线段树)

problem 给定数组 l,rl,rl,r。求有多少个非空集合 SSS&#xff0c;满足 ∀i,j∈Sli≤j≤ri\forall_{i,j\in S}\ l_i\le j\le r_i∀i,j∈S​ li​≤j≤ri​。 集合内对于任意一个点而言&#xff0c;其余点均能被自己的范围覆盖到。 n≤2e5n\le 2e5n≤2e5。 solution 分享一下…

【学习笔记】线性规划与对偶问题和LP对偶费用流([ZJOI2013]防守战线题解)

线性规划与对偶问题 原问题&#xff1a; min⁡{7x1x25x3}s.t.{x1−x23x3≥105x12x2−x3≥6xi≥0\min\{7x_1x_25x_3\} \\ s.t.\begin{cases} x_1-x_23x_3\ge 10\\ 5x_12x_2-x_3\ge 6\\ x_i\ge 0\end{cases} min{7x1​x2​5x3​}s.t.⎩⎪⎨⎪⎧​x1​−x2​3x3​≥105x1​2x2​−…

【学习笔记】DAG / 一般有向图的支配树 / 灭绝树

定义与声明 一个有向图 GGG。给定一个起点 sss&#xff0c;假设 sss 能到达所有点。 若去掉某个点 iii 后&#xff0c;sss 无法到达 jjj&#xff0c;则称 iii 为 jjj 的支配点。 显然支配点存在传递关系。 以 sss 为根&#xff0c;使得对于任意节点 iii&#xff0c;其树上祖…

[ZJOI2014] 星系调查(树上差分 + 数学推式子)

problem luogu-P3340 题面写得那么长&#xff0c;其实说白了就是求一条直线&#xff0c;使得若干个点到这条直线的距离平方的和最小&#xff0c;求这个最小值。 solution 我超爱数学&#xff0c;数学就是我的命&#xff0c;我一天不学数学我就难受&#xff01; 假设拟合出…

[ZJOI2014] 璀璨光华(bfs建图 + dfs搜索)

problem luogu-P3342 solution 你感觉这道题没考什么&#xff0c;又感觉考了什么 通过样例以及题面&#xff0c;我们并未获取到『立方体每个小方块的编号是按一定规则命名』的信息。 也就是说&#xff0c;我们需要通过输入的每个小方块相邻的编号的信息来建出这个立方体的…

cf1523A. Game of Life

cf1523A. Game of Life 题意&#xff1a; 包含n个元素的数组&#xff0c;数值为1或0&#xff0c;如果一个元素为0&#xff0c;并且其周围正好只有一个为1的元素&#xff0c;那么下一刻本元素也会变成1. 给你一个数值&#xff0c;问你m次时刻后数组的状态 题解&#xff1a; …

SignalR 中丰富多彩的消息推送方式

在上一篇 SignalR 文章中&#xff0c;演示了如何通过 SignalR 实现了简单的聊天室功能&#xff1b;本着简洁就是美的原则&#xff0c;这一篇我们也来聊聊在 SignalR 中的用户和组的概念&#xff0c;理解这些基础知识有助于更好的开发基于 SignalR 的应用&#xff0c;通过对用户…

Visual Studio 2019 使用 Live Share

一.前言Visual Studio 2019 在今天发布&#xff08;北京时间&#xff09;了&#xff0c;这次带来了一个比较有趣的 Live Share 功能&#xff0c;使用它可以进行更好的协作开发。主要功能&#xff1a;更多资料可看官方介绍&#xff1a;Visual Studio 实时共享什么是Visual Studi…

cf1523B. Lord of the Values

cf1523B. Lord of the Values 题意&#xff1a; 给你一个数组&#xff0c;有n个数&#xff0c;n为偶数&#xff0c;a1&#xff0c;a2…an 现在有两个操作&#xff1a; 对于i<j 操作1&#xff1a;aiaiaj 操作2&#xff1a;ajaj-ai 把原数组转换为-a1,-a2,-a3… 题解&#…