网络流题型总结
P4016负载平衡问题
N个环形排列的点,每个点之间的权值数量不相等,现在可以让每个点G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
题解:
首先为了让每个点收支达到平衡,我们可以先求出所有货物的数量,进而求得每个点货物数量的平均值。
那么对于当前仓库有两种可能:
1当前仓库的数量是比平均值大的,那么我们知道当前仓库是需要流出w[i]-avg数量的。
2当前仓库的数量是比平均值小的,那么我们知道当前仓库是需要流入avg-w[i]数量的
对于情况1,我们让这个点和汇点建立一个边,流量上限是w[i]-avg,费用为0,代表这个边必须流满。
对于情况2,我们让这个点和源点建立一条边,流量上限是avg-w[i],费用为0,代表这个边同样必须流满。
现在考虑单点,由于可以在相邻的点之间传递,我们在相邻点之间,建立一条流量上限为INF
,费用为1的边,代表每向这个点流入一个流量,费用为1。
这样跑一个最小费用最大流,就是本题的答案。
P4015 运输问题
W 公司有 m 个仓库和 n个零售商店。第 i个仓库有 ai 个单位的货物;第 j 个零售商店需要 bj个单位的货物。
货物供需平衡,即n个零售店需要的和m个仓库所拥有的货物相同
从第 i 个仓库运送每单位货物到第 j个零售商店的费用为 Ci,j 。
试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少
答案要求,两行分别输出最小运输费用和最大运输费用。
解决方法:
最小运输费用,其实计算的话,就是一个模版题。
问题在于计算最大运输费用。
我们还是利用类似负数转逆的思想,我们考虑把所有的单位运输费用全部设置成为负数,同样跑最小费用最大流,那么其实就转变成为最大费用最大流。
建图的话,其实也比较好建立
S连接仓库,流量上限为仓库货物量,费用为0
仓库连接商店,流量上限为INF,费用为ci,j
商店连接汇点,流量上限为商店需求货物量,费用为0
P4014 分配问题
有 n件工作要分配给 n 个人做。第 i个人做第 j件工作产生的效益为 ci,j。试设计一个将 n件工作分配给 n个人做的分配方案,使产生的总效益最大。两行分别输出最小总效益和最大总效益。每个人只能做一个工件
解决方法:
和运输问题非常类似,但是这里每个物品只能给一个人做。那么我们可以考虑,从源点到每工作一个限制,保证每个工作只能被做一次,同时每个人只能做一个工作。那么我们就从源点连接物品一个流量为1,费用为0的边,而对于每个人,连接汇点,流量上限为1,费用为0,在每个工件和人之间,连接流量为INF,费用为ci,j的边,跑最小费用最大流以及最大费用最大流。
P3355 骑士共存问题
在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击。
最大匹配=最小点覆盖
最小路径覆盖=|G|-最大匹配数
最大独立集=点数-最大匹配
证明:
把黑白两种位置看成二分图,黑色肯定不能攻击到黑色,白色也肯定不能攻击到白色。
而一个黑色的点一旦出现,那么周围一些白色的点不能同时存在。
我们考虑给不能同时存在的点连接一条流量为INF,
对于黑色类型的点,每个点由于只能放一个,每个点连接源点,流量为1
对于白色类型的点,每个点连接汇点,流量为1。
我们建立出来的图形,其实就是从s-黑点-白点-t。
我们知道这些点实际上是不能存在的,也就是说这些点所连接的汇点,流量应该为0,即最小割。由最小割=最大流,我们求这个图的最小割,即能保证所有无法同时存在的点,满足条件。
这其实就是二分图的最大独立集问题。
选出最多的点数=原来的点数-最大流
选出最多的点数=原来的点数-最小割
Ans=n*n-m-maxflow
P3254 圆桌问题
假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。
会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
解决方法:
保证每个单位代表数为ri,从源点连接每个代表,流量为ri。
保证每张餐桌容量限制,从餐桌连接到汇点,流量上限为ci。
然后对于每个代表团,连接每一张桌子一个流量上限为1的边,保证每个张桌子中,都是来自不同的代表团。
跑一个最大流和代表团总人数进行比较,如果相同代表有相应的方案,否则没有。
输出方案嘛,对于点查找和它相连的餐桌中。流量为0的,意味这个对于该代表团有向这个餐桌流了1的流量,也就是说这个餐桌被选中了。这样就能比较快速的打印答案。
P2756 飞行员配对方案问题
英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
解决方法:二分图最大匹配,网络流。在此不再赘述。
P2766最长不下降子序列问题
给定正整数序列x1,...,xn 。
(1)计算其最长不下降子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。
(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列。
解决方法:
对于问题1,之间利用n^2的dp,或者优化一下的dp即可。
对于问题2,每个数字只能使用一次,从问题1得到的dp数组入手。对于j<i并且dp[j]+1==d[i]那么我们在j和i之间连接一条流量上限为1的边,对于dp[i]=1的,显然应该由源点连接这个点,对于dp=s(最长不下降子序列的长度),连接这个点汇点,然后跑一个最大流,就是答案。这样连接实际上是有问题的,为什么?很简单
对于j-i之间连接了一条流量上限为1的边,不能保证j还和其他的点连接,我们为了避免出现这种尴尬的状况,进行拆点,把每个点拆成入点和出点,入点和出点连接一条流量限制为1的边代表这个点只能使用一次,然后对于j<i并且dp[j]+1==dp[i]我们可以把j的出点连接i的入点,流量限制为1,然后对于dp[i]==s,让改点的出点连接汇点,容量为1,
对于问题3,我们该如何跑呢?很简单,为了保证a[n]和a[1]可以多次使用,我们连接s和a[1]入点的流量设置成INF,a[1]入点和a[1]出点流量上限也设置成INF,如果dp[n]==s,我们设置a[n]的入点和a[n]的出点流量限制设置成INF,a[n]连接s的流量上限也设置成INF,在dp[n]!=s的时候,不能这样设置,因为流到当前a[n]入口的流量,当前点dp[n]并不满足dp[n]==s 那么也就不能这么连接,否则汇让跑到当前点的流量直接流到汇点,对答案产生贡献,实际是它并没有贡献的。
P2763 试题库问题
假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算法。
解决方法:
其实也很简单,我们为了保证试卷保护每个类型题的数目,把所需类型连接到汇点,流量上限设置成试卷所需的每种类型的量,然后源点连接每一道题,流量设置为1,保证每个题目只归一类,对于每个题目,对起所属类型,流量设置为1,跑最大流,看最大流是否和试卷所需的数目相同,如果是的话,代表有答案。打印答案的时候,打印的是每个类型p所属的题号,我们对类型号进行遍历,如果类型号->题号的流量为1,代表题号->类型号的流量为0,即该题选中的是这个类型。
P2765 魔术球问题
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。
对于给定的n,计算在n根柱子上最多能放多少个球
解决方法:
变换型网络流,这题看似和最大流一点关系都没有。。。实际上还是用了。。。
我们从1,2,3….n按顺序,由于每个数只能使用一次,因此需要拆点,把每个点拆成入点和出点,然后去枚举比这个数小,并且能和当前数字结合形成完全平方数。类似最小路径覆盖一样,把入点和出点相连,算出合并的数目。如果当前最大流量为0,代表已经无法满足上述条件,需要用新的柱子。
P2764 最小路径覆盖问题
给定有向图 G=(V,E) 。设 P 是 G 的一个简单路(顶点不相交)的集合。如果 V 中每个定点恰好在P的一条路上,则称 P 是 G 的一个路径覆盖。P中路径可以从 V 的任何一个定点开始,长度也是任意的,特别地,可以为 0 。G 的最小路径覆盖是 G 所含路径条数最少的路径覆盖。设计一个有效算法求一个 GAP (有向无环图) G 的最小路径覆盖。
求解方法:
首先我们考虑用n个点覆盖,然后考虑合并,每合并一条边,实际上就是让路径覆盖数目减一,那么我们只需要计算路径合并的数目。
我们把点拆成入点和出点,入点连接源点,出点连接汇点,如果两个点有边,那么用这个点的入点,连接这个点的出点,流量限制为1,那么我们算出的最大流就是最大匹配数目,也就是合并路径的数目,那么最小路径覆盖=n-合并路径数目。
也可以用二分图的相关定理去搞一搞
P2762 太空飞行计划问题
有m个实验,每个实验只可以进行一次,但会获得相应的奖金,有n个仪器,每个实验都需要一定的仪器,每个仪器可以运用于多个实验,但需要一定的价值,问奖金与代价的差的最大值是多少?对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
解决方法:
这是一道典型的最大权闭合子图。
这道题无非是让我们权衡奖金与代价,这两者是有我没他的,怎么去处理呢,我们先建立一张图,所有的实验与源点相连,容量为其奖金,所有的器材与汇点相连,容量为其价格,中间实验与器材相连,容量为无穷大。
这个时候跑最小割,其必定会割掉连接实验或容器的边,因为中间的边的代价为无穷大,一定不会被割掉。跑最小割相当于选择部分的实验和部分的仪器,剩下的实验和仪器就会被割掉,此时再用实验的总价值减去可能得到的最大值,即为其所要求的答案。
P1251 餐巾计划问题
一个餐厅在相继的 N天里,每天需用的餐巾数不尽相同。假设第 i天需要 ri块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s分(s<f)。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。
解决方法:
首先,我们拆点,将一天拆成晚上和早上,每天晚上会受到脏餐巾(来源:当天早上用完的餐巾,在这道题中可理解为从原点获得),每天早上又有干净的餐巾(来源:购买、快洗店、慢洗店)。
1.从原点向每一天晚上连一条流量为当天所用餐巾x,费用为0的边,表示每天晚上从起点获得x条脏餐巾。
2.从每一天早上向汇点连一条流量为当天所用餐巾x,费用为0的边,每天白天,表示向汇点提供x条干净的餐巾,流满时表示第i天的餐巾够用 。 3.从每一天晚上向第二天晚上连一条流量为INF,费用为0的边,表示每天晚上可以将脏餐巾留到第二天晚上(注意不是早上,因为脏餐巾在早上不可以使用)。
4.从每一天晚上向这一天+快洗所用天数t1的那一天早上连一条流量为INF,费用为快洗所用钱数的边,表示每天晚上可以送去快洗部,在地i+t1天早上收到餐巾 。
5.同理,从每一天晚上向这一天+慢洗所用天数t2的那一天早上连一条流量为INF,费用为慢洗所用钱数的边,表示每天晚上可以送去慢洗部,在地i+t2天早上收到餐巾 。
6.从起点向每一天早上连一条流量为INF,费用为购买餐巾所用钱数的边,表示每天早上可以购买餐巾 。 注意,以上6点需要建反向边!3~6点需要做判断(即连向的边必须<=n)