网络流24题
餐巾计划问题
将每天的早晚分开,分成两个点,然后建图
如果要让最大流等于每天用到的餐巾数量之和,那么一定要满足每天都要向汇点连一条容量为当天餐巾数量的边。
如何体现餐巾的重复利用呢?答案是从源点向每天晚上连容量为当天餐巾数量的边。
1 |
|
试题库问题
水题
1 |
|
运输问题
水题
1 |
|
圆桌问题
还是个水题…
1 |
|
骑士共存问题
网络流的优势在于,可以实现一种决策,使得每次操作都不会使结果变劣。所以拿到这个题我的第一反应是构建一种模型,当放置一个棋子之后,与其互斥的位置就自动被屏蔽掉,奈何本人太菜,此路不通。
于是换一种思维方式,利用最大流最小割求解。
通过观察可以发现,如果将棋盘使用国际象棋的方式黑白染色,那么互斥的位置颜色一定是不同的。于是可以从黑色的点向着互斥的白点连边。这样求得的最大流,即为必须去除的棋子。
1 |
|
航空路线问题
终于遇到一个比较好玩的题了指de了一下午bug
问题中说需要找到两条路径,并且使得点越多越好。所以很自然地想到把点数看成value。
难点在于,如何把“找到两条路径”化为最大流模型。
考虑拆点,把每个点拆成一个入点和出点两个点,两个点之间连一条容量为1,费用为1的边(如果是1和n点则容量为2)
对于原图中的边(u,v),则从u的出点向着v的出点连容量为2的边即可(容量设置为2是因为有可能有1到n的直达边,这条边是很有可能被走两次的,虽然其他边最多被走一次,但是如果都这样设置容量为2可以方便代码实现,而且不会影响正确性)。
然后再从源点向1的入点连边,从n的出点向汇点连边。
1 |
|
最小路径覆盖问题
考虑每个点都是一条单独的路径,然后再合并点。于是把点拆成两个,对于一条边(u,v),则连接(u2-1,v2),跑得的最大流代表着最大的合并次数,所以答案就是总点数减去最大流。
1 |
|
[CTSC1999]家园 / 星际转移问题
首先二分需要的时间,然后拆点,构建分层图。即从上一时刻的空间站向着下一时刻的空间站连一条容量为INF的边,然后转移边就是每个飞船的行动路线,若路径经过i,j,则为从t-1时刻的i点到t时刻的j点。然后跑最大流查看是否为K就可。
1 |
|
太空飞行计划问题
最小割的经典例题,还是挺有代表性的。
先说说如何建图:从源点连边到所有的实验,边权为实验的价值;从所有的实验器材到汇点连边,边权为器材的价格;对于每个实验,从该实验向着它所需要的器材连边,边权为INF。对所有的实验的价值求和,然后减去这个图上的最大流即为答案。
证明有很多,可以去洛谷的题解里面查看,这里简单介绍一下我的理解、
首先说明一下这个图中的割的含义:对于从源点连出的边,被割掉则表示不选择这条边,即没被割掉则表示选择该边;对于连向汇点的边,被割掉则表示选择这条边。这样一来,可以满足对于每个被选择的实验,其后继的实验器材一定被选择。所以一个合法的决策一定和该图的一个割对应。
易知答案=所有的实验的价值总和-一个合法的割的权值
所有实验的价值总和是定值,所以只需要最小化割的权值即可,所以最小割即为所求。
本题还有一个坑点在于输出方案。需要明确的是,不能利用跑完dinic后的边权余量来判断一条边是否被选择成为了割边。举个例子,一个实验价值为1,需要一个器材,该器材的花费也为1,所以跑完网络流后,这两条边的余量都是0,所以这个实验和器材要么都被选择,要么都不被选择,但是按照一般的逻辑来写的话,实验的边会被看成割掉,器材的边也会被看成被割掉,会导致输出方案错误。
如何解决呢?我们可以枚举每个实验,把它的边权设置为INF,表示这条边必须没有被割掉,如果这样算出来的最小割依然为原值,则说明这条边对应的实验一定在方案中。实验器材则可以直接通过已选择的实验确定。
1 |
|
最长k可重区间集问题
该题目的限制条件为同一个点上对应的区间数不得超过K
乍看之下很难用简洁的代码去描述这个限制。这里我们需要转换一下思维方式。
首先,由于区间是开区间,且端点值均为整数,所以我们可以把长度为1的线段看成考虑的基本元素。例如区间[i,i+1]代表的是其端点间所夹的长度为1的线段。
然后我们可以发现,除了区间端点之外的点,都不影响答案,所以可以离散化端点。
所以问题就转变为,如何找到一个区间集合,对于数轴上的每条长度为1的线段,覆盖它的区间不超过K
对于一个区间[l,r],我们连接接一条从l点连接到r的点,其中覆盖了r-l条线段,分别为[l,l+1],[l+1,l+2],…,[r-1,r],容量为1(因为一个区间只能最多选一次),价值为r-l
对于每两个相邻的点,连接一条容量为+∞的边,价值为0(走这条边相当于此时没有选区间)
我们构造一个源节点,将它放在数轴上的无穷远处,从该节点连出一条为容量为k的边到第一个线段(即同时只能在一个线段上选k个区间)
如果线段跨度比较大时,可以把端点离散化。
1 |
|
最长k可重线段集问题
该问题的模型同上一题。注意考虑一下线段的特殊情况即可。这里把端点和端点之间的线段部分都看成独立的点。
1 |
|
魔术球问题
问题的关键在于如何满足数字是连续的,这也是这道题与前面题目的不同之处。
考虑设计一个模型,使得一旦新的球被放到柱子上,流量便会增大。先说建图方式:将每个点拆成两个点,源点连向入点,出点连向汇点,边权都是1。然后对于能组成平方数的两个数对之间也连边,入点连向出点。
每次遇到一个新的球,就跑一边网络流,如果能跑通,说明当前这个球能被前面的某个球“接住”,否则必须额外新开一根柱子去放置这个球。
1 |
|
汽车加油行驶问题
观察到K比较小,于是比较容易地想到把当前的油量也看成一个状态,所以直接跑一个流量为1的最小费用流就行了。
注意车辆在一个地方最多被加满油一次,所以在没有加油站的地方加油时,可以直接把建加油站的钱加到油钱上面去,不需要单独判断。
1 |
|
负载平衡问题
直接说建图吧,如果一个仓库当前的货物量大于平均值sum,则从源点连一条容量为a[i]-sum的边,否则从仓库连向汇点,容量为sum-a[i],这两种边的费用均为零。然后在相邻点之间连容量为INF,费用为1的边。
1 |
|
火星探险问题
建图很简单,拆点就完了。
难点在于输出,这里使用了深搜的方式,详见代码
1 |
|