线性规划与网络流24题

来源:互联网 发布:格式工厂 mac 编辑:程序博客网 时间:2024/06/05 22:36

这是一套很经典的题目,在这里提供个人所总结的构图方法、解题思路,如有错漏欢迎指出。

 

1.飞行员配对方案问题(难度★☆☆☆☆)
 
解题思路:一道裸的最大二分匹配,也可以建立源汇用最大流解决,最后要输出方案。
 
 
2.太空飞行计划问题(难度★★★☆☆)
 
  这道题的原型其实就是胡伯涛《最小割模型在信息学竞赛中的应用》中说到的最大权闭合图的例题,也是黑书中介绍“最小割”模型的原题,因此是网络流中相当经典的题目之一。
 

解题思路:
 
  每个实验所需要的仪器,就是其必要条件,将所有实验、仪器都抽象成一个点,则可以依据这个拓扑关系构造拓扑图,有向边由实验指向相关的仪器,边权设为无穷大。对于每个实验,点权应该是正的(收入),而对于每件仪器,点权应该是负的(支出)。建立源汇,从源向各正权点连边,流量上限为点权,从各负权点向汇点连边,流量上限为点权绝对值,这样,点权就化成了边权。
  考虑此图的最小割边集,由两部分组成,一部分是原来正权点所化成的边,另一部分是原来负权点所化成的边(由于中间节点间的边权值为无限,不可能归入最小割边集)。前者的含义是“选上这些点的总收入”,后者的含义是“选上这些点的总支出”,由于是最小割,因此得到的是最小收入、最小必须的支出。因此,只要用所有实验的总收入,减去这部分实验的最小收入、最小必须支出,就是所求的最大收入。问题化为求图的一个最小割,也就是最大流,因此运行一次最大流算法就能得出结果,而具体方案也很简单,如果理解了上述解法,自然知道如何从图中提取方案。
 
  这道题目除去源汇,其实就是二分图,但这种构图方法可以解决闭合图上求最大点权集的问题,并不局限于二分图,具体可以看胡伯涛论文,而证明此方法的正确性,则黑书上说得较容易理解。
 
 
3.最小路径覆盖问题(难度★★☆☆☆)
 
解题思路:
 
  对于图上的所有点进行拆点,左边为点集X,右边是一一对应的点集Y,构造二分图。若原图存在边u -> v,则在二分图中有边u -> v',如此类推。然后 最小路径覆盖 = N – 最大二分匹配,证明略。运行一次匈牙利算法即可解决数量问题,但本题要求打印一个方案,下面做详细说明。
  对二分图运行一次匈牙利算法后得到所有点的匹配信息,若在二分图中存在匹配u -> v',则等价于原图中的有向边u -> v,将所有匹配边还原到原图中,得到的就是所求的最小路径覆盖方案了。这样的话,直观的做法就是根据匹配边,重新构造一幅图,找到入度为0的点依次遍历就得到方案了。另一种做法,找到点集Y中没有被匹配的所有点(v1',v2'……),这些节点对应的v1,v2……节点就是路径的头结点,对于每一个头结点依次遍历其子节点,就能得到每一条路径。显然,这里所说的点集Y中没有被匹配的节点,就是方法一中重构图的入度为0的节点。
 
 
4.魔术球问题(难度★★☆☆☆)
 
  这道题是黑书中介绍最小路径覆盖的例题,有一定的代表性。
 
解题思路:
 
  由于这道题目没有说明数据量的大小(如n的范围 or 保证数据中最多能放的球不超过多少等),所以先假设是数据量较小的情况来讨论。
  首先是构图,在一个小范围M内,若存在1 <= i < j <= M, 有(i+j是完全平方数),则构造一条有向边i -> j,如此可以得到有向无环图。易知题目所求的就是最小路径覆盖为n时,最多能放多少个球,我们便可以枚举 or 二分球数k,使得k个球恰好能被n条路径覆盖(k要尽可能大),求最小路径覆盖的方法同问题3,若数据量过大,此法则行不通了。
  在黑书中提到,利用二分图匹配求解后可以发现,n取任何可以验证的所有值时,最大值均为f(n) = (n*n/2 + n – 1/2)向下取整,证明略,但这个公式不易求得且不容易理解,更没有可扩展性(黑书中也提到,当条件“完全平方数”改变后,公式便不适用了,但匹配模型是适用的),更重要的是不能确定具体方案,而匹配模型可以如问题3中的方法构造方案。因此本题应该是构造匹配模型来解决的。
  总而言之,如果题目数据量小或者要求打印方案,直接构造匹配模型求解。否则,可以构造匹配模型得到数据量较小时的答案,通过找通项公式、找规律等方法来求解。
 
 
5.圆桌问题(难度★★☆☆☆)
 
  这道题与黑书中网络流的例题1的模型完全一样,只是背景稍有不同。
 
解题思路:
 
  将单位归为点集X、圆桌归为点集Y,由于每个单位的人都可以去任意圆桌,而且每个圆桌中同一个单位的人不超过一个,因此对于所有的xi,都向点集Y的每个节点连一条容量为1的边。建立超级源汇s、t,s向所有xi连边,容量为对应单位的总人数,所有yi向t连边,容量为每张圆桌的容量,求一次从s到t的最大流,如果最大流量等于总人数,则存在可行解,否则不存在可行解。若存在可行解,注意到任意一条边xi -> yi,若流通,说明第i个公司的一个代表被安排到第j张圆桌,因此遍历一次残留网络即可得到可行方案。(此题亦可用多重二分匹配来做)
 
 
6.最长递增子序列问题(难度★★★☆☆)   相似题目:POJ  3998
 
  这道题和黑书中网络流例题2的意思一样,但多出了第三小问。
 
解题思路:
 
  第一小问是DP的内容,但做法和第二小问有紧密关联,所以用求最长上升子序列的O(nlogn)的算法。该算法的过程,是依次求出x1、x2 …… xn的对应d[i]值,d[i]表示以xi结尾的最长上升子序列长度(这里我的理解和黑书上的讲解不同)。
 
构图步骤如下:
 
  A.依据这个d[i]值,来构造一个层次网络图,每一层的节点的d[i]值相同,假设最长上升子序列长度为k,若建立超级源点s连接所有d[i] = 1的节点,所有d[i] = k的节点连接超级汇点t,那么任意一条从s -> t的增广路径就是一个长度为k的上升子序列,上述连接的边流量上限均为无限。
 
  B.由于每个节点只能被选取一次,因此对于每个点都拆点,并将流量上限设为1。
 
  C.网络中间的连接要注意根据层次网络的要求,必须同时满足d[j] + 1 = d[i],xj < xi,xj排在xi前面,才可以连接一条流量上限为无限的边(xi -> xj)。
 
  图构造完毕,s到t的最大流就是第二问的结果,每一条增广路径对应着答案的一组最长上升子序列。但上述最后一个步骤比较麻烦,要充分理解求最长上升子序列的算法才行,因为构图的步骤可以和求最长上升子序列的长度k的过程完美结合。
 
  此题的第三问其实很简单,因为每个点只能选取一次才对所有点进行拆点,所以第三问只要将第二问中的x1、xn还原(不用拆点),s到t的最大流就是所求结果。
 
 
7.试题库问题(难度★★☆☆☆)
 
  这道题的描述很坑,看了很多遍都没搞明白,最后还是看样例才理解题意的。有n道题目,每道题目属于一个或多个类别,有k种类别,第i个类别需要有ki道题目,并且每道题目只能归入一个类别,问能否得出k份试卷,第i份试卷包含ki道属于该类别的题目。
 
解题思路:
 
  建立超级源汇,s到所有题目连上流量上限为1的边,这样每道题目就只能归入一个类别。每个类别都向t连接一条流量上限为ki的边。对于所有题目,均向其所属的类别连接一条流量上限为1的边。若所有连到t的边都满流,证明存在可行解。运行一次最大流算法后,对于题目i、类别j,若有流通过,证明将题目i归为类别j,根据此残留网络即可得出可行方案。(此题亦可用多重二分匹配来做)
 
 
8.机器人路径规划问题(难度★★★★★)
 
  这道题是黑书网络流中的课后习题,黑书上的描述为“本题非常困难,是著名GMPIR问题的简化版本。有兴趣的读者可以阅读本书主页。”
  该题有一点点像小时候玩过的小游戏“推箱子”,本人想不出好的解法,唯有暴力搜索,或者利用A*优化搜索,但都不是基于网络流的多项式复杂度算法,跪求高人指点。
 
 
9.方格取数问题(难度★★★☆☆)
 
  这道题是经典的最大点权独立集问题。最大点权独立集 + 最小点权覆盖集 = 所有点权和。
 
解题思路:
 
  在一个方格里取数,取了任意一个数则与其有公共边的所有数都不能取,因此可以将每个方格都看作一个节点,点权为方格内的数值,所有有公共边的方格可以看作其节点有边相连,如此,就是求这个无向图的最大点权独立集,只要求出最小点权覆盖集就可以了,下面详细说求解方法。
 
  对上述的无向图的每个节点进行拆点,如节点u可拆成u、u',规定u属于X集合,u'属于Y集合,这样可得到一个二分图。建立源汇s、t,s向所有X集合的点连接有向边,边权为原点权,所有Y集合的点向t连接有向边,边权同样为原点权,如此便将点权化作边权。对于原图中所有边,如存在,在新图中构造或者中任意一条,边权为INF。此时,这幅图中的最小割,就是原图的最小点权覆盖,因此从s到t运行一次最大流算法,即得到最小点权覆盖集,进而求出最大点权独立集。
 
  这里一共说到了三幅图,其实理解其中原理后,直接根据方格来构造最终的网络图求最大流即可。
 
 
10.餐巾计划问题(难度★★★☆☆)
 
  这道题目是最小费用最大流的模型,限制条件比较多,对于学习和理解构图很有帮助。
 
构图步骤如下:
 
  A.有N天,因此构造N个节点,编号为1 – N,建立源汇s、t。
 
  B.对于第i个节点,从s向其连接一条有向边,流量上限为INF,费用为买一条餐巾的费用p,如此满足了买餐巾的条件。
 
  C.对于第i个节点,向t连接一条有向边,流量上限为第i天需要的餐巾数ri,费用为0,如此该网络的最大流便满足了每天所需的餐巾数。
 
  现在考虑送洗条件,可以假设每天的餐巾刚刚够用,那么每天就剩下来ri条旧餐巾,这些旧餐巾可以做如下处理:先存放着、送去快洗、送去慢洗。
 
  D.另外构造N个节点,编号为N+1 – 2*N表示第i-N天的旧餐巾分配,从s向每个节点连接一条有向边,流量为每天旧餐巾数ri,费用为0。
 
  E.对于每个旧餐巾分配节点i,向第i+1个节点连接一条流量上限为INF,费用为0的边,表示处理方式为“先存放着”。
 
  F.对于每个旧餐巾分配节点i,向第i+m+m <= 2*N)个节点连接一条流量上限为INF,费用为快洗费用f,“送快洗”。
 
  G.对于每个旧餐巾分配节点i,向第i+n(n为慢洗天数,i+n <= 2*N)个节点连接一条流量上限为INF,费用为慢洗费用s,“送慢洗”。
 
  图构造完毕,从s到t运行一次最小费用最大流算法,即可得到所求的最小费用。
 
 
11.航空路线问题(难度★★★☆☆)
 
解题思路:
 
  首先利用字典树或者map将城市的名字映射成为1 – N的数字标号,再根据题目给出的边构造出的图就是一个基本的网络。题目有以下三个要求,我们按照其要求来构造相应的网络图。
 
  A.要求除起点外任何城市只能访问一次。我们只需要对原图的每个点都拆点,连接一条流量上限为1,费用为-1的边(稍后再解释费用的设定问题)。
 
  B.从节点1出发,到达节点N后再返回节点1。我们只需建立一个超级源点s,向节点1连接一条流量上限为2,费用为0的边,但这与拆点有了冲突,因此对于节点1可以特殊地不必拆点,或者可以看成对节点1进行“特殊的拆点方式”。若从超级源点到节点N的最大流为2,证明图中从1到N存在两条不同的路径。
 
  C.要求途经尽可能多的节点。由于A中的费用设定,每经过一个节点,费用则会-1,要求经历尽可能多的点,就等价于费用最小。
 
  因此,先将原网络的所有边的流量上限设为INF,费用为0,再根据上述步骤改造网络,求从s到N的最小费用最大流,若最大流为2,则存在可行解,费用的绝对值加1(节点1的费用没有算上)就是途径的节点总数,残留网络上会有两条从s到N的路径,将其中一条路径逆置后便得到实际的方案了。
 
 
12.软件补丁问题(难度★★★☆☆)
 
  这道题目的描述很繁杂,要仔细看清楚题意,而且根据所给出的样例可以知道题目“数据输入”部分的描述有错误的,我是根据样例来理解并最终确定题意的。
 
解题思路:
 
  以样例来说明,这道题的目的是将初始状态000(表示3个错误都存在)通过最小的代价转化为状态111(表示3个错误的被补丁修复了),可以看出,这里用到了二进制状态压缩,这也是题目构图的关键所在。样例总共有3个错误,我们可以假设一幅图,已经存在2^3个节点,标号为0 — 2^3-1,他们分别代表状态为000、001、010、011、100、101、110、111的节点,题目给出的补丁,则看成是各种状态间的转移条件,如第三个补丁 “2 0– -++”,0–可以代表011、111两个节点(为什么代表这些节点请仔细读题),-++只代表了100节点,因此,这里要连接两条有向边3->4、7->4,边权为2。当所有边都连接完(毕,我们可以发现可行解为000 -> 001 -> 010 -> 011 -> 100 -> 101 -> 110 -> 111,由000状态转化为111状态所需的最小代价是8,这也就是答案。
  扩展到N个节点的情况,也是依照上述的压缩方法构图,最多有2^20个节点,规模有点吓人,但边数有限,实际运行速度不会太慢。原来我想的是从0节点到2^N-1节点求一次最小费用最大流,由于这个最大流只可能为0或1,0表示无解,1表示有解,因此可以不用省去流量,直接求上述两个节点间的最短路。
 
 
13.星际转移问题(难度★★★☆☆)
 
  这道题是黑书介绍网络流中的例题4,分层图网络流。
 
解题思路:
 
  将每个太空站看成节点,太空船看成连接各太空站的边,但问题在于这些边(太空船)会随着时间的变化而循环地改变,应对这个变化的方法就是将网络按时间来分层,如飞船的路线是134,则在0时刻的1节点向1时刻的3节点连接一条边,流量上限为飞船的容量,同理,1时刻的3节点向2时刻的4节点连接一条同样的边、2时刻的4节点向3时刻的1节点连接一条同样的边,如此循环反复。还有一点需要注意,人可以在太空站里停留,因此第i层网络的节点要向第i+1层网络的自身连接一条流量上限为INF的边。
  建立一个源点s,向地球节点连接一条流量为k的边,我们从0时刻开始构造网络,每次计算从s到月球的最大流,若累计不足k则构造1时刻、2时刻……,直到t时刻,流量总量为k,则答案为t。由于存在无解的情况,需要设定一个最大层数,超过这个层数就判定为无解。
 
 
14.孤岛营救问题(难度★★★☆☆)
 
解题思路:
 
  这道题目和12题有点相似,都需要用到二进制状态压缩,0表示未解锁、1表示已解锁,有k种锁,也就有2^k种不同的状态,我们可以建立一个[2^k][N][M]的三维数组,第一维表示该状态下的解锁情况,剩下两维是迷宫,从[0][1][1]开始BFS,拿到第a种钥匙就转移到a种锁已解锁的迷宫的相同位置继续搜索,如果到达任意状态的[][N][M]点则有解。
  此外,同样用状态压缩,但用迭代加深DFS来求解代码可以更简洁,而且实际搜索只需在一个N*M空间进行,空间开销也可以相应减少很多,重点是要注意DFS过程状态的变化,以及解锁、回溯时重新锁上等细节问题。
 
 
15.汽车加油行驶问题(难度★★★☆☆)
 
解题思路:
 
  网格中的每个点看作一个节点,每个点与其相邻的点分别连接一条边,若x坐标或y坐标减小了费用就为B,否则为0。此外,油量这一变量随时间的增加而减少,因此可以仿照对时间的处理方法,构造分层网络,显然,这题只需构造k层网络即可,第1层表示满油,第k层表示没油。值得注意的是,若某点有加油站,则所有非第1层的该点都应该向第1层的自身节点连接一条费用为A的边,如此便满足了加油的条件,同理,任意非第1层的点都应该向第1层的自身节点连接一条费用为C的边,如此便满足了增设油库的条件。由于是流恒为1,求最小费用最大流就等价于求起点到终点的最短路,这里和12题是一样的。
 
 
16.数字梯形问题(难度★★☆☆☆)
 
解题思路:
 
  首先构造一幅基础网络图,由于有三个不同的规则,所以先忽略流量的设置方式,只考虑费用。题目要求的是最大费用,因此将所有数字取相反数就变成了最小费用最大流问题。每个数字看作一个节点,先根据题目的条件连接边,费用均为0,然后就是拆点,将点权变成边的费用。建立源汇s、t,s连接顶端的节点,下端的所有节点连接t,费用为0。
 
  规则1,所有边的流量上限都设置为1,则路径不相交。拆点间的边流量也设置为1,则点不相交。
  规则2,所有边的流量上限设置为1,但拆点间的边流量上限设置为INF,允许点相交。
  规则3,所有边的流量上限设置为INF,拆点间的边流量上限也设置为INF。
 
  得到上述三个网络后,分别求出最小费用最大流,费用的绝对值就是答案。
 
 
17.运输问题(难度★☆☆☆☆)
 
解题思路:
 
  这是一道比较裸的费用流问题。将仓库看成二分图的X集合,零售商店看成Y集合,根据题目建立源汇s、t,s连接所有X集合中的点,流量上限为仓库货物量,费用为0,所有Y集合的点连接t,流量上限为零售商店需要的货物量,费用为0。X集合与Y集合中的点,对于每对点ij,连接一条流量上限为INF,费用为cij的边,对s到t求一次最小费用最大流就是其最少运送费用,求一次最大费用最大流就是其最多运送费用。
 
 
18.分配问题(难度★☆☆☆☆)
 
解题思路:
 
  不难发现,这道题与17题可以用完全一样的费用流模型解决,可以参考17题,这里不再赘述。此外,这题和17题的一个小差异是这里X集合与Y集合的点数是完全相同的,因此也可以用解决二分图最大权匹配的KM算法来解决。
 
 
19.负载平衡问题(难度★★☆☆☆)
 
解题思路:
 
  首先每个仓库作为节点,每个节点与相邻两个节点分别连接一条边,流量上限为INF,费用为1。然后建立源汇s、t,求出库存量的平均值ave。对于所有节点i,若库存大于ave,则从s向其连接一条流量上限为ai-ave、费用为0的边,若库存小于ave,则从节点i向t连接一条流量上限为ave-ai、费用为0的边,从s到t的最小费用最大流就是答案。
 
 
20.深海机器人问题(难度★★☆☆☆)
 
  这道题输入数据的方式很怪,要仔细多看才能理解。
 
解题思路:
 
  网格中的每个交点看成一个节点,每个节点与其正北、正东的相邻节点各连接一条边,流量上限为1,费用为给出的标本价值,因为同一条边,机器人经过只能在首次获得其标本价值,但依然能继续通过,所以要为上述的两条边添加一条重边,流量为INF,费用为0。建立源汇s、t,s连接所有a个机器人所在的起始位置,流量上限为ki,费用为0,所有b个目的地连接t,流量上限为ri,从s到t的最大费用最大流就是答案。
 
 
21.最长k可重区间集问题(难度★★★★☆)    相似题目:POJ  3680
 
解题思路:
 
  先将所有区间的端点离散化,得到a、b、c……严格递增的序列,将较小的点向相邻的较大的点连接一条有向边,每条边的流量上限为INF,费用为0,这样实际上构造了一条离散化后的线段。对于每个区间(x,y),x向y连接一条有向边,流量上限为1,费用为长度值y-x,这样就构造了所有的区间。最后,建立源汇s、t,s向最小的端点值节点连接一条有向边,流量上限为k,费用为0,最大端点值节点向t连接一条有向边,流量上限为k,费用为0。从s到t的最大费用最大流就是答案。
  这道题目的构图方法和一般的网络流有所不同,上述的构图方法是参考了网上解题报告的。
 
 
22.最长k可重线段集问题(难度★★★★☆)
 
解题思路:
 
  这道题是21题的延伸,变成了2维、长度为两点间距离,且数据很大,需要用到long long。由于题目要求的是使得x轴上任一点p,x = p与线段相交的个数不超过k,也就是说可以把所有线段投射到x轴上,事先计算线段的长度后就化成一维了,和21题的做法一样。但这里要注意一个问题,如线段(x1, y1)、(x2, y2),若x1不等于x2,投射到x轴上是开区间(x1, x2),若x1等于x2,投射到x轴上应该是一个点x1,因此要对所有点进行拆点,才不至于形成自环从而寻找最大费用增广路时陷入死循环。
 
 
23.火星探险问题(难度★★☆☆☆)
 
  这道题和20题本质上是一样的,只是需要打印方案。
 
解题思路:
 
  将每个网格看作一个节点。对于每个节点若为障碍点,则不必处理。若为石块,就要进行拆点,拆点间连接一条流量上限为1,费用为1的边,再连接一条流量上限为INF,费用为0的边(这里可以参考20题),然后当成平坦点处理。若为平坦点,则向其正南、正东的邻接非障碍节点连接一条流量为INF,费用为0的边。最后建立源汇s、t,s连接(0,0)点,流量上限为探测车数,费用为0,(P,Q)点连接t,流量上限为INF,费用为0。从s到t求一次最大费用最大流,每次用最短路算法找出的可行路径依次按要求输出就是答案。
 
 
24.骑士共存问题(难度★★☆☆☆)
 
  这道题是黑书上介绍二分图独立集的原题,是第9题的简化版本。最大独立集 + 最小覆盖集 = 节点数N
 
解题思路:
 
  对每个格点进行拆点,一个点归入X集合,另一个点归入Y集合,构成一个二分图。若两个格点u、v存在冲突,则连接两条边、,但注意其中任意一个点为障碍的时候都不必连接。求二分图的最大匹配k,“N – k/2”就是最终答案。若上述两条边、只严格地连接一条,则答案应为“N – k”,其中的原因请自己思考。关于上述结论的证明等问题就忽略了,黑书和网上的资料都非常多,也可以自己尝试证明。
原创粉丝点击