Ⅰ 运筹学中的图论问题
很多实际的生产问题都能被抽象成一张大的图。具体一点的例子,比如需要在若干个城市之间铺设铁路或者架设电网,那么城市就是图里面的点,铁路电网就是图里面的边。抽象一点的例子,比如完成一个项目的过程中所有可能出现的状态都可以视为一个点,而状态到状态之间的转换就是边。上一篇文章中我们说过运筹学是处理实际生产生活中遇到的问题的。一旦实际问题被抽象成了一个图的模型(注意与机器学习里面的图模型区分开来),很多图论里面的算法就可以用来解决实际问题,所以图论是运筹学当中的一个很大的分支。今天我们就介绍一下几个图论的基本算法及其在生产生活中的应用。
一最小生成树
比如现在要在若干个村子之间架设电网,保证每个城市都通上电(先不考虑电网输电能力大小)。虽然理论上讲,任何两个村子之间都可以架设电线,不过那样的话成本很到,不划算,我们需要在所有可能的连线里面找到一组总长最短的边,保证这些边把每个村子都连上了。在图论中,这是一个典型的最小生成树问题。有两种解决最小生成树的方法,第一种办法是把所有的边按照从小到大的顺序添加到图里面,如果产生回路就舍弃它,直到覆盖了所有的点。另一种方法是把图上的边按照从大到小的顺序删除,直到再删下去就一定会产生离散的点为止。
二最短路径
图论中应用最广的问题可能就是最短路径问题了。地图上很多城市之间都有道路相连,想从一个城市到另一个城市,往往有多种选择,可是走那条路距离最短呢?如果地图规模不大,我们可以一眼就看出来。可是随着地图规模变大,就很难再一眼看出来了,需要有严格的算法保证找到最短路径。目前已经有了很多种最短路径算法,他们的基本思想也不尽相同。以着名的Dijkstra算法为例,它每次会选择距离“所有已经选择过了的点”中距离最近的下一个点,一步步的迭代下去。这个流程保证了算法会按照距离出发点由近到远的顺序选择每一个点。
三最大流-最小割问题
油气输送网络又许多不同的边组成,每一条边的运输能力有限。输送油气资源的时候,为了最大化运输量,需要合理安排通过每一条边的油气流量。这就是在一个网络寻找最大流的问题(等价于寻找最小割)。解决问题的想法很简单,找到一组边,它们把整个网络分成了两部分,流的源和目的地址分属于这两个部分。我们称这样一组边为图的一个分割。由于所有的油气流都要通过分割中的边,所以最大流其实受制于分割的流通能力的。于是最大流应该等于流通能力最小的分割。剩下的问题,就是一步步调整,找到最小分割了。
Ⅱ 最小割集等于最大流
最大流是一种运输方案,割集是分割网络发点与收点的一组弧集合,割集中包含的是一组弧,而这些弧的发点跟收点分别在两个点集,最小割集只是最大流的一部分,因而不对吧
Ⅲ 网络流的资料
编辑本段定义
图论中的一种理论与方法,研究网络上的一类最优化问题 。1955年 ,T.E. 哈里斯在研究铁路最大通量时首先提出在一个给定的网络上寻求两点间最大运输量的问题。1956年,L.R. 福特和 D.R. 富尔克森等人给出了解决这类问题的算法,从而建立了网络流理论。所谓网络或容量网络指的是一个连通的赋权有向图 D= (V、E、C) , 其中V 是该图的顶点集,E是有向边(即弧)集,C是弧上的容量。此外顶点集中包括一个起点和一个终点。网络上的流就是由起点流向终点的可行流,这是定义在网络上的非负函数,它一方面受到容量的限制,另一方面除去起点和终点以外,在所有中途点要求保持流入量和流出量是平衡的。如果把下图看作一个公路网,顶点v1…v6表示6座城镇,每条边上的权数表示两城镇间的公路长度。现在要问 :若从起点v1将物资运送到终点v6去 ,应选择那条路线才能使总运输距离最短�这样一类问题称为最短路问题 。 如果把上图看作一个输油管道网 , v1 表示发送点,v6表示接收点,其他点表示中转站 ,各边的权数表示该段管道的最大输送量。现在要问怎样安排输油线路才能使从v1到v6的总运输量为最大。这样的问题称为最大流问题。
最大流理论是由福特和富尔克森于 1956 年创立的 ,他们指出最大流的流值等于最小割(截集)的容量这个重要的事实,并根据这一原理设计了用标号法求最大流的方法,后来又有人加以改进,使得求解最大流的方法更加丰富和完善 。最大流问题的研究密切了图论和运筹学,特别是与线性规划的联系,开辟了图论应用的新途径。
目前网络流的理论和应用在不断发展,出现了具有增益的流、多终端流、多商品流以及网络流的分解与合成等新课题。网络流的应用已遍及通讯、运输、电力、工程规划、任务分派、设备更新以及计算机辅助设计等众多领域。
网络流算法
一、网络流的基本概念
先来看一个实例。
现在想将一些物资从S运抵T,必须经过一些中转站。连接中转站的是公路,每条公路都有最大运载量。如下图:
每条弧代表一条公路,弧上的数表示该公路的最大运载量。最多能将多少货物从S运抵T?
这是一个典型的网络流模型。为了解答此题,我们先了解网络流的有关定义和概念。
若有向图G=(V,E)满足下列条件:
1、 有且仅有一个顶点S,它的入度为零,即d-(S) = 0,这个顶点S便称为源点,或称为发点。
2、 有且仅有一个顶点T,它的出度为零,即d+(T) = 0,这个顶点T便称为汇点,或称为收点。
3、 每一条弧都有非负数,叫做该边的容量。边(vi, vj)的容量用cij表示。
则称之为网络流图,记为G = (V, E, C)
譬如图5-1就是一个网络流图。
1.可行流
对于网络流图G,每一条弧(i,j)都给定一个非负数fij,这一组数满足下列三条件时称为这网络的可行流,用f表示它。
1、 每一条弧(i,j)有fij≤cij。
2、 除源点S和汇点T以外的所有的点vi,恒有:
该等式说明中间点vi的流量守恒,输入与输出量相等。
3、 对于源点S和汇点T有:
这里V(f)表示该可行流f的流量。
例如对图5-1而言,它的一个可行流如下:
流量V(f) = 5。
2.可改进路
给定一个可行流f=。若fij = cij,称<vi, vj>为饱和弧;否则称<vi, vj>为非饱和弧。若fij = 0,称<vi, vj>为零流弧;否则称<vi, vj>为非零流弧。
定义一条道路P,起点是S、终点是T。把P上所有与P方向一致的弧定义为正向弧,正向弧的全体记为P+;把P上所有与P方向相悖的弧定义为反向弧,反向弧的全体记为P-。
譬如在图5-1中,P = (S, V1, V2, V3, V4, T),那么
P+ = {<S, V1>, <V1, V2>, <V2, V3>, <V4, T>}
P- = {<V4, V3>}
给定一个可行流f,P是从S到T的一条道路,如果满足:
那么就称P是f的一条可改进路。(有些书上又称:可增广轨)之所以称作“可改进”,是因为可改进路上弧的流量通过一定的规则修改,可以令整个流量放大。具体方法下一节会重点介绍,此不赘述。
3.割切
要解决网络最大流问题,必须先学习割切的概念和有关知识。
G = (V, E, C)是已知的网络流图,设U是V的一个子集,W = V\U,满足S U,T W。即U、W把V分成两个不相交的集合,且源点和汇点分属不同的集合。
对于弧尾在U,弧头在W的弧所构成的集合称之为割切,用(U,W)表示。把割切(U,W)中所有弧的容量之和叫做此割切的容量,记为C(U,W),即:
例如图5-1中,令U = {S, V1},则W = {V2, V3, V4, T},那么
C(U, W) = <S, V2> + <V1, V2> + <V1, V3>+<V1, V4>=8+4+4+1=17
定理:对于已知的网络流图,设任意一可行流为f,任意一割切为(U, W),必有:V(f) ≤ C(U, W)。
通俗简明的讲:“最大流小于等于最小割”。这是“流理论”里最基础最重要的定理。整个“流”的理论系统都是在这个定理上建立起来的,必须特别重视。
下面我们给出证明。
网络流、可改进路、割切都是基础的概念,应该扎实掌握。它们三者之间乍一看似乎风马牛不相干,其实内在联系是十分紧密的。
二、求最大流
何谓最大流?首先它必须是一个可行流;其次,它的流量必须达到最大。这样的流就称为最大流。譬如对图5-1而言,它的最大流如下:
下面探讨如何求得最大流。
在定义“可改进路”概念时,提到可以通过一定规则修改“可改进路”上弧的流量,可以使得总流量放大。下面我们就具体看一看是什么“规则”。
对可改进路P上的弧<vi, vj>,分为两种情况讨论:
第一种情况:<vi, vj>∈P+,可以令fij增加一个常数delta。必须满足fij + delta ≤ cij,即delta ≤ cij – fij。
第二种情况:<vi, vj>∈P-,可以令fij减少一个常数delta。必须满足fij - delta ≥ 0,即delta ≤ fij
根据以上分析可以得出delta的计算公式:
因为P+的每条弧都是非饱和弧,P-的每条弧都是非零流弧,所以delta > 0。
容易证明,按照如此规则修正流量,既可以使所有中间点都满足“流量守恒”(即输入量等于输出量),又可以使得总的流量有所增加(因为delta > 0)。
因此我们对于任意的可行流f,只要在f中能找到可改进路,那么必然可以将f改造成为流量更大的一个可行流。我们要求的是最大流,现在的问题是:倘若在f中找不到可改进路,是不是f就一定是最大流呢?
答案是肯定的。下面我们给出证明。
定理1 可行流f是最大流的充分必要条件是:f中不存在可改进路。
证明:
首先证明必要性:已知最大流f,求证f中不存在可改进路。
若最大流f中存在可改进路P,那么可以根据一定规则(详见上文)修改P中弧的流量。可以将f的流量放大,这与f是最大流矛盾。故必要性得证。
再证明充分性:已知流f,并且f中不存在可改进路,求证f是最大流。
我们定义顶点集合U, W如下:
(a) S∈U,
(b) 若x∈U,且fxy<cxy,则y∈U;
若x∈U,且fyx>0,则y∈U。
(这实际上就是可改进路的构造规则)
(c) W = V \ U。
由于f中不存在可改进路,所以T∈W;又S∈U,所以U、W是一个割切(U, W)。
按照U的定义,若x∈U,y∈W,则fxy = cxy。若x∈W,y∈U,则fxy = 0。
所以,
又因 v(f)≤C(U,W)
所以f是最大流。得证。
根据充分性证明中的有关结论,我们可以得到另外一条重要定理:
最大流最小割定理:最大流等于最小割,即max V(f) = min C(U, W)。
至此,我们可以轻松设计出求最大流的算法:
step 1. 令所有弧的流量为0,从而构造一个流量为0的可行流f(称作零流)。
step 2. 若f中找不到可改进路则转step 5;否则找到任意一条可改进路P。
step 3. 根据P求delta。
step 4. 以delta为改进量,更新可行流f。转step 2。
step 5. 算法结束。此时的f即为最大流。
三、最小费用最大流
1.问题的模型
流最重要的应用是尽可能多的分流物资,这也就是我们已经研究过的最大流问题。然而实际生活中,最大配置方案肯定不止一种,一旦有了选择的余地,费用的因素就自然参与到决策中来。
图5-8是一个最简单的例子:弧上标的两个数字第一个是容量,第二个是费用。这里的费用是单位流量的花费,譬如fs1=4,所需花费为3*4=12。
容易看出,此图的最大流(流量是8)为:fs1 = f1t = 5, fs2 = f2t = 3。所以它的费用是:3*5+4*5+7*3+2*3 = 62。
一般的,设有带费用的网络流图G = (V, E, C, W),每条弧<Vi, Vj>对应两个非负整数Cij、Wij,表示该弧的容量和费用。若流f满足:
(a) 流量V(f)最大。
(b) 满足a的前提下,流的费用Cost(f) = 最小。
就称f是网络流图G的最小费用最大流。
2.算法设计
我们模仿求最大流的算法,找可改进路来求最小费用最大流。
设P是流f的可改进路,定义 为P的费用(为什么如此定义?)。如果P是关于f的可改进路中费用最小的,就称P是f的最小费用可改进路。
求最小费用最大流的基本思想是贪心法。即:对于流f,每次选择最小费用可改进路进行改进,直到不存在可改进路为止。这样的得到的最大流必然是费用最小的。
算法可描述为:
step 1. 令f为零流。
step 2. 若无可改进路,转step 5;否则找到最小费用可改进路,设为P。
step 3. 根据P求delta(改进量)。
step 4. 放大f。转step 2。
step 5. 算法结束。此时的f即最小费用最大流。
至于算法的正确性,可以从理论上证明。读者可自己思考或查阅有关运筹学资料。
2.最小费用可改进路的求解
求“最小费用可改进路”是求最小费用最大流算法的关键之所在,下面我们探讨求解的方法。
设带费用的网络流图G = (V, E, C, W),它的一个可行流是f。我们构造带权有向图B = (V’, E’),其中:
1、 V’ = V。
2、 若<Vi, Vj>∈E,fij<Cij,那么<Vi, Vj>∈E’,权为Wij。
若<Vi, Vj>∈E,fij>0,那么<Vj, Vi>∈E’,权为-Wij。
显然,B中从S到T的每一条道路都对应关于f的一条可改进路;反之,关于f的每条可改进路也能对应B中从S到T的一条路径。即两者存在一一映射的逻辑关系。
故若B中不存在从S到T的路径,则f必然没有可改进路;不然,B中从S到T的最短路径即为f的最小费用可改进路。
现在的问题变成:给定带权有向图B = (V’, E’),求从S到T的一条最短路径。
考虑到图中存在权值为负数的弧,不能采用Dijkstra算法;Floyd算法的效率又不尽如人意——所以,这里采用一种折衷的算法:迭代法。
设Short[k]表示从S到k顶点的最短路径长度;从S到顶点k的最短路径中,顶点k的前趋记为Last[k]。那么迭代算法描述如下:(为了便于描述,令n = |V’|,S的编号为0,T的编号为n+1)
step 1. 令Short[k] +∞(1≤k≤n+1),Short[0] 0。
step 2. 遍历每一条弧<Vk, Vj>。若Short[k] + <k, j> < Short[j],则令Short[j] Short[k] + <k, j>,同时Last[j] k。倘不存在任何一条弧满足此条件则转step 4。
step 3. 转step 2.
step 4. 算法结束。若Short[n + 1]= +∞,则不存在从S到T的路径;否则可以根据Last记录的有关信息得到最短路径。
一次迭代算法的时间复杂度为O(kn2),其中k是一个不大于n的变量。在费用流的求解过程中,k大部分情况下都远小于n。
3.思维发散与探索
1)可改进路费用:“递增!递增?”
设f从零流到最大流共被改进了k次,每i次选择的可改进路的费用为pi,那么会不会有p1≤p2≤p3≤……≤pk呢?
2)迭代法:“小心死循环!嘿嘿……”
迭代法会出现死循环吗?也就是说,构造的带权有向图B中会存在负回路吗?
3)费用:“你在乎我是负数吗?”
网络流图中的费用可以小于零吗?
4)容量:“我管的可不仅是弧。”
网络流图中的“容量”都是对弧而言的,但若是给每个顶点也加上一个容量限制:即通过此顶点的流量的上限;任务仍然是求从S到T的最小费用最大流。你能解决吗?
四、有上下界的最大流
上面讨论的网络流都只对每条弧都限定了上界(其实其下界可以看成0),现在给每条弧<Vi, Vj>加上一个下界限制Aij(即必须满足Aij≤fij)。
例如图5-9:
弧上数字对第一个是上界,第二个是下界。若是撇开下界不看,此图的最大流如图5-10(a)所示,流量是6;但若是加入了下界的限制,它的最大流量就只有5了,具体方案见图5-10(b)。
那么有上下界的网络最大流怎么求呢?
一种自然的想法是去掉下界,将其转化为只含上界的网络流图。这种美好的愿望是可以实现的。具体方法如下:
设原网络流图为G = (V, E, C, A),构造不含下界的网络流图G’ = (V’, E’, C’):
1、 V’ = V∪{S’, T’}
2、 对每个顶点x,令 ,若h-(x)≠0,就添加一条弧<S’, x>,其上界为h-(x)。
3、 对每个顶点x,令 ,若h+(x)≠0,就添加一条弧<x, T’>,其上界为h+(x)。
4、 对于任何<Vi, Vj>∈E,都有<Vi, Vj>∈E’,其上界C’ij = Cij – Aij。
5、 新增<T, S>∈E’,其上界CTS = +∞。
在G’中以S’为源点、T’为汇点求得最大流f’。若f’中从S’发出的任意一条弧是非饱和弧,则原网络流图没有可行流。否则可得原图的一个可行流f = f’ + A,即所有的fij = f’ij + Aij。(其正确性很容易证明,留给读者完成)
然后再求可改进路(反向弧<Vi, Vj>必须满足fij≥Aij,而非fij≥0),不断放大f,直到求出最大流。
我们看到,上几节所讨论的一种可行网络流实际上是{Aij = 0}的一种特殊网络流,这里提出的模型更一般化了。解决一般化的复杂问题,我们采取的思路是将其转化为特殊的简单问题,加以研究、推广,进而解决。这是一种重要的基本思想:化归——简单有效。基于这种思想,请读者自行思考解决:
1、 有上下界的最小流。
2、 有上下界的最小费用最大流。
五、多源点、多汇点的最大流
已知网络流图有n个源点S1、S2、……、Sn,m个汇点T1、T2、……、Tm,,求该图的最大流。这样的问题称为多源点、多汇点最大流。
它的解决很简单:
1、 增设一个“超级源”S’,对每个源点Si,新增弧<S’, Si>,容量为无穷大。
2、 增设一个“超级汇”T’,对每个汇点Ti,新增弧<Ti, T’>,容量为无穷大。
3、 以S’为源点、T’为汇点求最大流f。
4、 将f中的S’和T’去掉,即为原图的最大流。
算法正确性显然。
六、顶点有容量限制的最大流
上一节已经提出了这个问题,即对于进出每个顶点的流量也规定一个上限,这样的最大流如何求?
既然我们已经解决了“边限制”问题,现在何不把“点限制”问题转化为“边限制”呢?具体办法如下:
1、 对除源点和汇点之外的每个顶点i拆分成两个顶点i’和i’’。新增一条弧<i’, i’’>,其容量为点i的流量限制。
2、 对于原图中的弧<i, j>,我们将其变换成<i’’, j’>。
3、 对变换后的图求最大流即可。
这里我们又一次运用到了化归的思想:将未知的“点限制”问题转化为已知的“边限制”问题。
七、网络流与二部图的匹配
{二部图和匹配的定义可参见本书专门介绍二部图匹配的章节}
设二部图为G = (X, Y, E)。
增设点S’,对于所有i∈X,新增弧<S’, Xi>,容量为1;增设点T’,对于所有i∈Y,新增一条弧<Yi, T’>,容量也为1。原图中所有的弧予以保留,容量均为+∞。对新构造出来的网络流图以S’为源点、T’为汇点求最大流:流量即为最大匹配数;若弧<Xi, Yj>(i∈X,j∈Y)的流量非零,它就是一条匹配边。
二部图最大匹配问题解决。
那么二部图的最佳匹配问题又如何?
仍然按照上述方法构图。同时令原图中弧的费用保持不变;新增弧的费用置为0。然后以S’为源点、T’为汇点求最小费用最大流即可。最大流的费用即为原二部图最佳匹配的费用。
复制的我快吐了~
Ⅳ 算法基础
谨以此文,感谢我在这个学校最喜欢的两个老师之一——肖my老师。本文基本为老师上课说讲授内容加上一部分自己的感悟拼凑而来,写作文本的目的是为自己的算法课程留下一点点东西,站在老师肩膀上形成粗糙的框架,方便以后的复习以及深入。文笔有限,其中包含的错误还请多多包容,不吝赐教。
to do list:
时间复杂度中递归树法;动规,分治新的感悟;
点覆盖:一组点的集合,使得图中所有边都至少与该集合中一个点相连。
支配集:一组点的集合,使得图中所有的点要么属于该集合,要么与该集合相连。
最大团:在一个无向图中找出点数最多的完全图。
独立集:一组点的集合,集合中的顶点两两不相邻。(团转过来)
SAT问题:也称布尔可满足性问题。给一组变
其中Ci被称为句子。
点覆盖<->独立集<->最大团
最小割:割是一组边集。如s-t割就是如果去掉这些边,将把原图划分为两个点集,其中一个点集包含s,一个点集包含t。(两个是指不相连,而不是代表不存在边相连,如反向边)
decision problem: 是否存在。
search problem:找到一个解。
(这个还能扩展,比如decision problem在多项式时间内解决,所以他是P问题吗)
渐进符号:
注意以上三种都是紧的,对应的两个小写的符号是不紧的,即如下图所示:
概念:算法的时间复杂度是一个函数,用于定性描述算法的运行时间。注意,这个一个代表算法输入字符串长度的函数。
[注]输入字符串长度是一个比较关键的理解,比如在背包问题中,其时间复杂度为O(nW),因为W不定,所以只能是一个伪多项式时间。
比较:c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n! < n^n
大致:常数<对数<幂函数<指数函数<阶乘
对于指数是n相关的进行比较,优先比较指数,再比较底数。
记住一个特例:n (logn)<n!<n n
计算:
一般来说,计算采用主方法和递归树法,其中递归树技巧性比较强,主方法其实也是递归树推导归纳而来,且主方法能得到一个比较紧的结果。
主方法:
f(n) = af(n-b)+g(n) =>O( a^(n/b) *g(n) )
P:decision problems有一个多项式算法。
NP(nondeterministic polynomial-time):decision problems能够在多项式时间内验证。
NPC:NP完全问题,首先这个问题是NP的,其次,其他所有问题都可以多项式时间内归约到它。
NPH:如果所有NP问题都可以多项式时间归约到某个问题,则称该问题为NP困难。
因为NP困难问题未必可以在多项式时间内验证一个解的正确性(即不一定是NP问题),因此即使NP完全问题有多项式时间的解(P=NP),NP困难问题依然可能没有多项式时间的解。因此NP困难问题“至少与NP完全问题一样难”。
一些NP问题能在多项式时间内解决,因为 P∈NP
NP难类型问题的证明:
先选好一个已知NP难的问题,然后将已知NP难问题多项式归约到要证明的问题上。先给出这个归约,然后再证明这个归约的正确性。
NPC类型问题的证明:
证明一个问题Y是NPC问题,先说明Y是NP的,然后找到一个NPC问题X,将这个问题X归约到问题Y上,即证明完成。
常见的NPC问题(重要,规约的时候有用!):
packing problems: set-packing,独立集
覆盖问题:集合覆盖问题,顶点覆盖问题
严格满足问题(constraint satisfaction problems):SAT,3SAT
序列问题:哈密尔顿回路,旅行商问题
划分问题:3D-matching, 3着色问题
数字问题:子集合问题(子集元素之和为t),背包问题
其他:分团问题(是否存在一个规模为k的团)
规约的概念与理解
规约:意味着对问题进行转换,例如将一个未知的问题转换成我们能够解决的问题,转换的过程可能涉及到对问题的输入输出的转换。
自归约:search problem <=p decision problem
归约:A归约到B,也就是说,我们对A套一个函数f,在f函数的作用下形成一个新的问题,对这个问题运用B的黑盒解法,能够解决问题A。
(B <=p A)一般说来,B问题如果可以归约到A问题,也就是说,一个解决A问题的算法可以被用做子函数(子程序)来解决B问题,也就是说,求解B问题不会比求解A问题更困难。因此,如果B问题是困难的,那么A问题也就是困难的,因为不存在求解A问题的高效算法。(最后一句不懂)
我简单说一下我理解的规约,以X规约到Y为准,大概分成两个方面:
注:在 三 的一些实例中细品。
概念:在对问题求解时,总是做出在当前看来是最好的选择。
贪心的证明:先假设贪心算法得到的解不是最优解,假设S1是贪心算法得到的解,而S2是所有最优解中和S1具有最多相同元素的解,然后比较S1和S2,观察S1和S2中第一个(最前面一个)不一样的元素,然后在贪心解S2中将不一样的元素换成S1中的那个元素得到另一个最优解S3,这样S3和S1比S2和S1有更多相同元素,和假设S2是与S1有最多相同元素的最优解矛盾,这样来推导S1是最优解。
我的理解:假设这个不是最优的,但是一定存在一个最优的解在某一个位置之前和我当前解结构是一样的,那么在这个位置,选最优解也可以选当前解,不影响最终答案。
[注]概念很简单,但是实际操作的时候,贪心的角度很重要,同样的贪心,方向对了,算法就是对的。
例子:
给你一系列活动,每个活动有一个起始时间和一个结束时间,要求在活动不冲突的情况下找到一种有最多活动的安排。
对于这个问题,我们有一下几种贪心的角度:
①将任务按照 开始时间 升序排列。
②将任务按照 结束时间 升序排列。
③将任务按照 任务时长 升序排列。
④对于每一个任务,都记录与其他任务冲突的数量,按照 冲突数量 的升序排列。
其中1,3,4都是不可以的。
任务结束时间的贪心证明(反证法):
假设贪心不是最最优的,那我们在最优解中找一个与当前解有最相似的解。
由图可以知道,贪心贪的就是最早结束,所以如果不是最优,那么最优的结束时间一定晚于贪心的结束时间。
由上图就可以证明。
最大流通常与最小割相联系。
f 为任意一个流,cap为容量,对于任意的s-t割出来的点集(A,B),v( f ) <= cap(A, B)。
当流增加到与割的容量相等时候,就不可能再有增长空间了,称为最大流。
对于割的容量来说,不同的割法会有不同流量,有些割法永远不会有流达到,比如部分A = {s}, B = {V - s},这种把源点割出来的割法。
综上,通过这种感性的认识,如果能找到一个最小的割,那么这个割就一定是最大能跑到的流(如果流能更高的话在这个割上就会超过容量,反证。)
上图为一条增广路,一条增广路即为一条s-t的路径,在路径上仍有流可以跑,其曾广的流就是该条路径上最小的剩余容量。(相当于每找一条增广路,就至少有一条边达到满流。)
直到在图中找不到增广路,此时已经达到了最大流。
找ST集合:把满流的边去掉,从S出发走到能到的点,遍历的点就是S集合;剩下的点就属于T集合。注意,如果找到了在找S集合的时候找到了T点,说明还可以继续找增广路。
[补]有一个很有趣的延伸,如多源点多终点问题。问:如果我有两个源点s1,s2,两个终点t1,t2,我想求一组流,使得s1-t1,s2-t2的流达到最大,是否可以加一个源点S,S与s1,s2相连,边流无限大;加一个终点T,T与t1,t2相连,边流无限大,然后这组ST的最大流即可。——答案是No,无法保证是s1-t1,s2-t2,有可能交错。
例子讲的感觉不是特别好,对理解感觉起不到很大作用,希望以后有新的想法后进行补充。
规约是一个重要的概念和思想。
一个图的 最大独立集 与 最小点覆盖 是不相交的两个点集,它们的并就是整个点集。
个人理解:独立集和点覆盖都是从点的角度进行划分的,如果我们从边的角度来看,①一个最小的点覆盖即为我集合中的每一个点都尽可能与更多的边相连,②同时,一条边的两个端点中,只能有一个端点在最小点覆盖中[下注]
[注]我们假设有一条边两个端点(u,v)都在点覆盖之中,首先显然u,v都不是端点,因为假设u是端点的话只需要选择v即可;
给一个集合S和一堆S的子集S1,S2,...,Sm,问是否存在存在k个子集,使它们的并集为S。
构造:
集合为点,集合中的元素为边,有相同元素的边相连。(注意如果某一元素只在一个子集中出现,应该怎么处理呢!)
规约:在构造的图中找最小的点覆盖,选中的点能覆盖所有的边即为对应集合的并集能包含所有的元素。所以就完成了集合覆盖到点覆盖的规约。
构造:每个句子构造一个三角形,把对应变量但是相反取值的点相连。
规约:3SAT的有一个特点就是,每一个句子中至少有一个为真即可,每个句子都必须是真。将相同变量相反取值相连的目的就是,在最大独立集中,比如选择x为真,则剩下所有句子中x-ba一定不会被选中,同时由独立集和构造出来三角形的性质可以知道,每一个句子,有且仅有一个会被选中(为真)。如上图,x1-ba为真,x2-ba和x3任选一个为真即可满足。
search problem <=p decision version
比如:如果能在多项式时间内找到一个哈密尔顿圈,那么就能在多项式时间内找到一个哈密尔顿圈(删边)
在此再谈P和NP:
我们知道有些问题是可以从搜索问题规约到判断问题的,也就是所该问题如果能在多项式内判断,那么久能在多项式中搜索到,那么我们只需要说,这个判断问题能在多项式时间内求解,就叫做P问题,也就是上图红字的意思;那NP问题呢,必须要给出一个解的实例,判断的是这个实例是否满足求解问题,这个才是上图中的红字。比如,我如果能在多项式时间内判断哈密尔顿圈是否(Yes/No)存在,那这个就是ploy-time algorithm,如果我给出了一系列点,能过多项式时间内判断这些点能否构成哈密尔顿圈,那这个就是poly-time certifier。
构造:把一个点拆分成三个点。
构造:(下面两个图要连在一起看)
从行的角度看,一行代表一个变量;从列的角度来看,每三列代表一个句子。两边中一边是两个点,一边是一个点,所以有k个句子的话,每一行有3k+3个节点。从哈密尔顿圈的答案转到3SAT的答案看这个圈在每一行是从左到右还是从右到左。
子集和问题:给一个集合S,问是否能在集合中选取元素,使得总和为W。
构造:如下图,按照前六行和前三列进行分割,可以分成4部分,其中1,3,4部分是固定的,即在第一部分,变量v列和 变量为v(包括变量及取反)的行对应的格子为0,其余为0;第三部分全为0;第四部分按照12依次写下来。第二部分,如果Ci句子中有变量v,则记为1,因为一个句子只有三个变量,可以简单通过第二部分每一列和为3进行判定。此时集合已经构造出来,W为111444,与上面的规约相似,可以通过3SAT的简单性质进行感性的认知。
近似的想法很简单,要解决一个问题,我们希望能够做到①求解结果是最优的 ②在多项式时间内解决 ③对于任意的实例都能够通过该算法解决。现在对于部分问题,无法完全满足以上要求,所以就牺牲了①,但是我们希望结果不是盲目的,所以就引入了近似的概念。
近似算法。比如2-近似,认为W为近似解,W 为最优解,在求最小值的情况下W<=2W ;在求最大值的情况下,W>=1/2W*
给m个机器和n个任务,每个任务有一个ti的执行时间,我们认为完成最后一个任务所需的时间为负载时间,希望能够让这个负载时间最短。
第一种:将任务依次放在机器上,当某个机器空闲时立即放入新任务。此时是2近似的。
证明:
引理1.最短时间安排是大于等于任务中时间最长的任务,L* >= max tj
我们在考虑放入最后一个任务前,根据我们放置的规则,该机器是耗时最短,也就是说,该机器此时的用时是低于除掉最后一个任务后的平均时长,更低于所有任务的平均时长(引理2);再根据引理1,最后一个任务应该是小于最优解的。
补充:
在这里,我还想讨论一下这个近似算法的中等于符号,先上结论:等号不一定能够找到一个实例,但是可以构造出一种结构,通过取极限求得,我们认为这样 也算是紧的。
构造实例:有m个机器,其中m(m-1)个任务的用时为1,1个任务的用时为m。肯定有一种任务集合,可以按照以下方式进行安排,此时的贪心解为19。
此时最佳的解为10,如下图:
通过推广可以知道此时的比为(2m-1)/m,当m取极限,能够达到2倍。
第二种:将任务从大到小排序,然后依次放在机器上,当某个机器空闲时立即放入新任务。此时是2近似的。
引理3:如果有大于m个任务,那么L*>=2t(m-1)。证明:t(m+1)是目前最短的任务,且目前所有机器上都有任务了,所以该任务加入时最优的情况不过是加入设备的原有任务刚好和t(m+1)相等,即等号。
(2近似)在n个点中,选取k个中心点,使得这些中心点能够以半径R的圆包含所有的点,让其中最大的半径最小,如下图所示:
基础:距离需要满足的三个定理①(同一性)dist(x, x) = 0 ②(自反)dist(x, y) = dist(y, x) ③(三角不等式)dist(x, y) <=dist(x, z)+dist(z, y)
r(C)为C集合中所有点的最大覆盖半径。(需要求min r(C))
算法:在点集中任选一个作为中心点,然后重复以下步骤k-1次:选取距离已选点集中最远的点,加入点集。
证明:先假设r(C )< 1/2 * r(C)以选好的点画半径为1/2 * r(C)的圆,显然可知[注],这个圆里有且仅有一个r(C )中的点。那么根据在下图中,根据三角不等式可以得出:
[注]在每个点上r(c )一定会包含到c点,而r(C )<1/2 * r(C),相当于大圆套小圆,所以c*一定在c的圆中。
(2近似)问题还是很好理解的,在点上加权值,要找一个点覆盖,使得权值最小。如下图左边就是一个带权的最小点覆盖。
算法: 任选一条边(i, j)加上代价,这个代价从零开始,且这个代价的最大值低于i和j节点的权值。显然,这个边权值的最大值取决于两个端点权值的最小值,我们认为当边权值与点权值相等时,对应的那个点是紧的。把所有紧的点找出来即为点覆盖。
流程:
证明:
引理:边权之和小于等于点覆盖的点权之和。这主要是由于涉及到一条边上两个点都被选(紧的)的情况,感性认知可以看上图,缩放证明如下:
w(S)是等于所选的节点的权值之和的,等于所选节点节点所对应的边权之和,可以把它放大到所有节点对应边权之和,这样因为一条边(u, v)在u上算过一次后还要在v上算一次,所以等于边权和的两倍。再由上面引理可得。
主要为了线性规划和整数规划。
(2近似)没啥好说的,只需要把方程构造出来就行了。
由于求解出来结果不一定是整数,所以我们认为某一点的值大于1/2,就选入点集。
证明:
因为xi+xj >=1,且都是正数,那必至少一个点是大于1/2的(反证,两个都小于1/2则和小于1)。
给你n个物品和一个背包,每个物品有一个价值v和一个大小w,背包的容量是W,要求让背包装下尽可能大价值。
背包的时间复杂度:O(nW)
注意其中n表示物品的个数,无论是1个还是999个,他都是多项式的,这个很好理解。但是W就不一样了,这是一个数字。我理解的是这个数字会很奇特,比如1.00001,比如99999,这些有可能看起来不大但是实际在处理的时候很难处理的数字,统一的来说,如果我们把这些数字放在电脑上,都会以二进制的方式存储起来,有些数字用十进制表示很小,但是放在二进制上面就会很大,由W导致不能在多项式时间内解决(找不到一个范围/上界来框它)。
算法: 为了处理这个问题,我们改动了dp的状态转移方程,要让这个转移方程和W无关[注]。
此时还不是多项式的,然后我们再对value进行约。[注]
[注]这两步中,我们把w改成v,并对v进行近似处理。OPT的含义变成了,在面对是否选择第i个物品时,要想让价值达到当前值,最少的weight。理由是更改后的误差是可以忍受的:对v进行近似,结果只会出现最大价值的上下误差,如果对w进行近似,则有可能出现该物品不能放入背包中,导致整个物品直接放弃的情况。
Ⅳ 高分:网络流问题
一、引言
网络流算法是一种高效实用的算法,相对于其它图论算法来说,它的模型更加复杂,编程复杂度也更高。但是它综合了图论中的其它一些算法(如最短路径、宽度搜索算法),因而适用范围也更广,经常能够很好地解决一些搜索与动态规划无法解决的非np问题。
网络流在具体问题中的应用,最具挑战性的部分是模型的构造,它没用现成的模式可以套用,需要我们对各种网络流的性质了如指掌(比如点有容量、容量有上下限、多重边等等),根据具体的问题发挥我们的创造性。一道问题经常可以建立多种模型,不同的模型对问题的解决效率的影响也是不同的,本文通过实例探讨如何确定适当的模型,提高网络流算法的效率。
二、网络流算法时间效率
当我们确定问题可以使用最大流算法求解后,就根据常用的ford-fulkerson标号法求解;而最小(大)费用最大流问题也可用类似标号法的对偶算法解题。ford-fulkerson标号法的运行时间为o(ve2),对偶法求最小费用流的运行时间大约为o(v3e2)。
显然,影响网络流算法的时间效率的因素主要是网络中顶点的数目与边的数目。这二个因素之间不是相互独立的,而是相互联系,矛盾而统一的。在构造网络模型中,有时,实现了某个因素的优化,另外一个因素也随之得到了优化;有时,实现某个因素的优化却要以增大另一因素为代价。因此,我们在具体问题的解决中,要坚持"全局观",实现二者的平衡。
三、模型的优化与选择
(一)减少模型的顶点数与边数,优化模型
如果能根据问题的一些特殊性质,减少网络模型中的顶点的数目和边的数目,则可以大大提高算法的效率。
例1:最少皇后控制
在国际象棋中,皇后能向八个方向攻击(如图1(a)所示,图中黑点格子为皇后的位置,标有k的格子为皇后可攻击到的格子)。现在给定一个m*n(n、m均不大于于50)的棋盘,棋盘上某些格子有障碍。每个皇后被放置在无障碍的格子中,它就控制了这个格子,除此,它可以从它能攻击到的最多8个格子中选一个格子来控制,如图1(b)所示,标号为1的格子被一个皇后所控制。
请你编一程序,计算出至少有多少个皇后才能完全控制整个棋盘。
图1(a) 图1(b)
输入格式:
输入文件的第一行有两个整数m和n,表示棋盘的行数与列数。接下来m行n列为一个字符矩阵,用''.''号表示空白的格子,''x''表示有障碍的格子。
输出格式:
输出文件的第一行仅有一个数s,表示需要皇后的数目。
sample input
3 4
x...
x.x.
.x..
sample ouput
5
问题分析]
如果本问题用简单的搜索来做,由于题目给的棋盘很大,搜索算法很难在短时间内出解。由于一个皇后在棋盘最多只能控制两个格子,因此最少需要的皇后数目的下界为[n*m/2]。要使得皇后数目最少,必定是尽量多的皇后控制两个格子。如果我们在每两个能相互攻击到的格子之间加上一条有向弧,则问题很类似于二分图的最大匹配问题。
[模型一]
1. 将每个非障碍的格子按行优先编号(0~m*n-1)。
2. 将上述的每个格子i折成两个格子i''和i'''',作为网络模型中的顶点。
3. 若格子i可以攻击到格子j且i<j,则在模型中顶点i''到j''''之间加上一条有向弧,容量为1。
4. 增加一个源点s,从s点向所有顶点i''添上一条弧;增加一个汇点t,从所有顶点j''''到t添上一条弧,容量均为1。
图1(b)所示的棋盘,对应的模型为:
图2
显然,任一解对应于以上模型的一个最大匹配。且最大匹配中,匹配数必定是偶数。因此至少需要的马匹数为m*n-障碍数-最大匹配数/2。
[模型二]
如果我们将棋盘涂成黑白相间的格子,则某皇后控制的两个格子一定是一个是黑格,另一个是白格(如图3),不妨设这两个格子中皇后在白格子上。于是,我们将n*m个格子分成两部分白格与黑格。因此我们可以将模型一优化为:
图3
1.将棋盘中的所有格子分成两个部分,对所有的格子进行编号,每个白格与它能攻击到的黑格之间(障碍除外)添上一条从白格到黑格的弧,构成一个二分图。
2.增加一个源点s,从s点向所有非障碍的白格添上一条弧;增加一个汇点t,从所有非障碍的黑格到t添上一条弧。
3.设置所有的弧的流量为1。
图1(b)所示的棋盘,对应的模型为:
图4
[两种模型的比较]
显然,模型二的顶点数与边数大致是模型一的一半。下面是在bp环境下两种模型的时间效率比较(p166/32m):
模型一 模型二
可扩展性 不易打印出一种解 容易打印出一种解
模型二正是根据问题的特殊性(即马的走法),将网格中的格点分成白与黑两类,且规定马只能从白格跳到黑格,从而避免将每个格点折分成两个点,减少模型的顶点数,同时也大大减少了边的数目。达到了很好的优化效果。
(二)综合各种模型的优点,智能选择模型
有时,同一问题的各种模型各有特色,各有利弊。这种情况下,我们就要综合考虑各种模型的优缺点,根据测试数据智能地选择问题的模型。
例2火星探测器(ioi97)
有一个登陆舱(pod),里边装有许多障碍物探测车(mev),将在火星表面着陆。着陆后,探测车离开登陆舱向相距不远的先期到达的传送器(transmitter)移动,mev一边移动,一边采集岩石(rock)标品,岩石由第一个访问到它的mev所采集,每块岩石只能被采集一次。但是这之后,其他mev可以从该处通过。探测车mev不能通过有障碍的地面。
本题限定探测车mev只能沿着格子向南或向东从登陆处向传送器transmitter移动,允许多个探测车mev在同一时间占据同一位置。
任务:计算出所有探测车的移动途径,使其送到传送器的岩石标本的数量最多,且使得所有的探测车都必须到达传送器。
输入:
火星表面上的登陆舱pod和传送器之间的位置用网络p和q表示,登陆舱pod的位置为(1,1)点,传送器的位置在(p,q)点。
火星上的不同表面用三种不同的数字符号来表示:
0代表平坦无障碍
1代表障碍
2代表石块。
输入文件的组成如下:
numberofvehicles
p
q
(x1y1)(x2y1)(x3,y1)…(xp-1y1)(xpy1)
(x1y2)(x2y2)(x3,y2)…(xp-1y1)(xpy2)
(x1y3)(x2y3)(x3,y3)…(xp-1y3)(xpy3)
…
(x1yq-1)(x2yq-1)(x3,yq-1)…(xp-1yq-1)(xpyq-1)
(x1yq)(x2yq)(x3,yq)…(xp-1yq)(xpyq)
p和q是网络的大小;numberofvehicles是小于1000的整数,表示由登陆舱pod所开出的探测车的个数。共有q行数据,每行表示火星表面的一组数据,p和q都不超过128。
[模型一]
很自然我们以登陆舱的位置为源点,传送器的位置为汇点。同时某块岩石由第一个访问到它的mev所采集,每块岩石只能被采集一次。但是这之后,其他mev可以从该处通过,且允许多个探测车mev在同一时间占据同一位置。因此我们将地图中的每个点分成两个点,即(x,y)à(x,y,0)和(x,y,1)。具体的描述一个火星地图的网络模型构造如下:
1. 将网格中的每个非障碍点分成(x,y)两个点(x,y,0)和(x,y,1),其中源点s = v(1, 1, 0),汇点t = v(maxx, maxy, 1)。
2. 在以上顶点中添加以下三种类型的边e1,e2,e3,相应地容量和费用分别记为c1、c2、c3以及w1、w2、w3:
u e1 = v(x, y, 0) -> v(x, y, 1),c1 = maxint,w1 = 0。
u e2 = v(x, y, 0) -> v(x, y, 1),c2 = 1,w2 = -1(这里要求(x, y)必须是矿石)
u e3 = v(x, y, 1) -> v(x'', y'', 0),c3 = maxint,w3 = 0.
其中x''=x+1 y''=y 或x''=x y''=y+1,1 <= x'' <= maxx,1 <= y'' <= maxy,且(x'' y'')非障碍。
从以上模型中可以看出,在构造的过程中,将地图上的一个点"拆"成了网络的两个节点。添加e1型边使得每个点可以被多次访问,而添加e2型边使得某点上的矿石对于这个网络,从s到t的一条路径可以看作是一辆探测车的行动路线。路径费用就是探测车搜集到的矿石的数目。对于网络g求流量为numberofvehicles的固定最小费用流,可以得到问题的解。
[模型二]
事实上,如果我们只考虑这numberofvehicles辆车中每辆车分别依次装上哪些矿石。则每辆车经过的矿石就是一条流,因此我们以网格中的矿石为网络的顶点建立以下的网络流模型。
1. 将网格中的每个起点(网格左上角)能到达,且能从它能到达终点(右下角)的矿石 (x,y)点分成左点(x,y,0)和右点(x,y,1)两个点,并添加源点s和汇点t。
2. 在以上顶点中添加以下五种类型的边e1,e2,e3,相应地容量和费用分别记为c1、c2、c3以及w1、w2、w3:
u e1 = v(x, y, 0) -> v(x, y, 1),c1 = 1,w1 = -1。
u e2 = v(x, y, 1) -> v(x'', y'', 0),c2 = 1,w2 = 0(矿石点(x, y)可到达矿石点(x'',y''))。
u e3 = s -> v(x, y, 0),c3 = 1,w3 = 0。
u e4 = v(x, y, 1)->t,c4 = 1,w4 = 0。
u e5=s->t,c5=maxint,w5=0。
由于每个石块被折成两个点,且容量为1,就保证了每个石块只被取走一次,同时取走一块石块就得到-1的费用。因此对以上模型,我们求流量为numberofvehicles的最小费用流,就可得到解。
[两种模型的比较]
1.模型一以网格为顶点,模型二以矿石为顶点,因此在顶点个数上模型二明显优于模型一,对于一些矿石比较稀疏,而网格又比较大的数据,模型二的效率要比模型一来得高。且只要矿石的个数不超过一定数目,模型二可以处理p,q很大的数据,而模型一却不行。
2.模型一中边的数目最多为3*p*q,而模型二中边的数目最坏情况下大约为p*q*(p+1)*(q+1)/4-p*q。因此在这个问题中,若对于一些矿石比较密集且网格又比较大的数据,模型二的边数将大大超过模型一,从而使得时间效率大大低于模型一。
下面是网格中都是矿石的情况比较(piii700/128m ,bp7.0保护模式):
numberofvehicles=10 模型一 模型二
通过以上数据,可知对于p,q不超过60的情况,模型一都能在10秒内出解。而模型二则对于p、q=30的最坏情况下速度就很慢了,且p、q超过30后就出现内存溢出情况,而无法解决。
因此,对于本题,以上两种模型各有利弊,我们可根据测试数据中矿石稀疏程度来决定建立什么样的模型。若矿石比较稀疏,则可以考虑用建立如模型二的网络模型;若矿石比较密集则建立模型一所示网络模型。然后,再应用求最小费用最大流算法求解。对于p,q>60,且矿石比较多情况下,两种模型的网络流算法都无法求解。在实际的应用中问题经常都只要求近似解,此时还可用综合一些其它算法来求解。
四、结束语
综上所述,网络流算法中模型的优化是网络流算法提高效率的根本。我们要根据实际问题,从减少顶点及边的角度综合考虑如何对模型进行优化,选择适当的模型,以提高算法的效率。对于有些题目,解题的各种模型各有优劣时,还可通过程序自动分析测试数据,以决定何种情况下采用何种模型,充分发挥各种模型的优点,以达到优化程序效率的目的。