ImageVerifierCode 换一换
格式:DOCX , 页数:20 ,大小:137.25KB ,
资源ID:8316159      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/8316159.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(网络流基础及应用.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

网络流基础及应用.docx

1、网络流基础及应用网络流基础及应用一.引例 运输方案下图为联结产品产地V1和销地V6的交通网,每一边(Vi,Vj)代表从Vi到Vj的运输线,产品经这条边由Vi输送到Vj,边旁的数字表示这条运输线的最大通行能力(简称容量)。产品经过交通网从V1输送到V6,现要求制定一个输送方案,使V1运到V6的产品数量最多。下面是一个可行的输送方案,边旁的数字为该运输线的实际运输量(单位:吨)。该运输方案表示:2吨产品沿有向路P1(V1,V2,V4,V6)运到销地;1吨产品沿有向路P2(V1,V2,V5,V6)运到销地;2吨产品沿有向路P3(V1,V3,V5,V6)运到销地。总共有5吨从V1运到V6。运输方案的可

2、行必须满足以下三个条件:实际运输量不能是负的;每条边的实际运输量不能大于该边的容量;除了起点V1和终点V6,对其他顶点(中间点)来说,不能囤积物资,即运到它那儿的物资是多少,从它那儿运走的物资也应该是多少。运输方案的改进:根据这个运输网,是否可增大运输量?改进1:我们找到一条有向路P4(V1,V2,V3,V4,V6)可再增加1吨物资运输量,改进的方案如下:改进2:有向路P5(V1,V3,V4,V6)还可增加1吨运输量:改进3:观察有向路P6(V1,V3,V2,V4,V6)中,将正方向的边(V1,V3)、(V2,V4)、(V4,V6)都可增加运输量,而反方向的边(V3,V2)的运输量为1,现将反

3、向边(V3,V2)的运量调到正向边(V2,V4)上去完成,这样有向路P6(V1,V3,V2,V4,V6)的运量可增加1(想一想为什么可以这样做)。至此,再找不到可“改进”的有向路了,所以,该交通网的最大运输量为8吨。通过上述实例分析,包含了流量因素的问题,是一类特殊的图。引例给出的交通网其具体的物理模型是多种多样的。比如网络的有向边可以表示为城市之间的公路、电信网之间的通讯线路、天然气站之间的输气管道等;边的容量则可以表示为允许通过的物资数量、汽车数量、速率或最大信号流量等。这一类特殊的图,称为网络流图。网络流图中需要解决的基本问题是求最大流问题。二.网络流图与最大流类似于上述交通网,可构造下

4、列称为网络流图的模型。1、网络流图的构造设G=(V,E)为一简单有向图。当且仅当只有一个入度为0(d(z)=0)的点,在V中指定该顶点为源点(记为Z),当且仅当有一个顶点出度为0的顶点,为汇点(记为Z),对于每一条边(Vi,Vj)E,赋予一个非负数Cij=0,叫做该边的容量。记为D=(V,E,C)(图示参见引例)2、网络的流对于网络流图D=(V,E,C)的每一条边(Vi,Vj)给定一个非负数fij,且满足下列条件:0=fij=Cij(容量限止条件)除源点和汇点外,其余顶点Vi恒有fij=fki(中间点流量守恒,即平衡条件)这时D=(V,E,C)中的流称为D的可行流f。3、关于D的可行流当所有f

5、ij=0,称为零流,零流一定是可行流。对于源Z和汇Z有fZj=fjZ=数叫做网络流的流量。当fij=Cij时,称边(Vi,Vj)饱和,表示流f对于该边饱和。达到最大值时的流f,称为D=(V,E,C)的最大流。三.求最大流的理论基础1、割切概念某些边的集合设D=(V,E,C)是已知的网络流图,假定S是V的一个子集,且S满足ZS Z (not)S且令S为S的补集,这样把顶点集V分成S和S两个部分,其中ZS,Z S对于一个端点在S,而另一个端点在S的所有边的集合,叫做网络流图D的一个割切,用(S,S)表示。下图用虚线划去的表示一个割切,其中S=Z,b,c,d,S=a,Z。割切容量C(S,S):在割切

6、(S,S)中,把从S到S的边容量和叫做这割切的容量。上边割切容量C(S,S)=CZa+Cba+CbZ+CdZ=4+3+2+4=132、定理:对于已知的网络流,从源点Z到汇点Z的流量的最大值小于等于任何一个割切的容量,即Max =Min C(S,S)。证明:当Vi为网络流图的任一中间点时,根据平衡条件,恒有fij-fji=0 当i=Z时,fZj= 设(S,S)为一任一个切,则有(fij-fji)= 注:iS,Z(not)S,ZS当iZ时,由式得0当i=Z时,由式得又因为SS=V所以(fij-fji)= (fij-fji)+ (fij-fji)= 式中(fij-fji)的两个下标都是对S的全体求和

7、,其展开式中任意一项fpq都一一对应一项-fpq,所以(fij-fji)=0即由式得(fij-fji) = 再由于0=fijCij,所以fij-fji=fij=Cij由式=(fij-fji)= Cij= C(S,S)故有Max =Min C(S,S)3、最大流量最小割切定理(Ford-Fulkerson定理)在一个给定的网络流图上,流的极大值等于割切容量的最小值,即Max =Min C(S,S)(下面的证明是构造性的,可以从中引出求最大流的算法思想)证明:(求证思路:由于已知Max =Min C(S,S)是不能进一步增加流量,直到使Max =Min C(S,S)在网络流图D=(V,E,C)中,

8、定义从源点Z到汇点Z的道路:设Z=V0,V1,.,Vn-1,Vn=Z为D上的顶点序列,对于i=0,1,.,n-1,恒有(Vi,Vi+1)或(Vi+1,Vi)边是D的一条边。则称V0,V1,.,Vn是一条从Z到Z的道路。由于D是有向图,道路上边的方向与道路方向一致的边称为前向边P+,反之称为后向边P-。道路上边的饱和:前向边若fij=Cij,后向边若fij=0,称边(Vi,Vj)为关于该道路上的饱和边。若从Z到Z的道路上所有的边均不饱和,即对于P+若fij0,则称这条路为可增广道路。修改可增广道路上每条边的流量,同时保持网络流的可行性,达到流量的增加,其增量的确定方法如下:Cij-fij P+f

9、ij P-令ij=取=Min(ij),为增量。就是对可增广道路P的每一条前向边流量增加,每一条后向边流量减少,从而使得整个网络流的流量获得增加(这是显而易见的)下面论证Max =Min C(S,S)设网络流图D的流量f达到极大,我们构造一个割切(S,S)如下若Z S,则有一条从Z到Z的道路,Z=V0,V1,.,Vk=Z,这条道路上所有的边均不饱和,因而是条可增广道路,这和f是最大流的假设矛盾。ZS若xS,且fxy0,则yS显然Z S(Z的出度d(Z)=0),所以(S,S)是一个割切。按照子集S的定义,若xS,yS,则fxy=Cxy若yS,xS,则fyx=0所以=(fxy-fyx)= fxy=C

10、(S,S)即Max =Min C(S,S)通过以上论证,可知当D中找不到可增广道路时,此时的流为最大流;当D中的流最大时,一定存在容量最小的割切(S,S)四.求网络最大流的算法根据上述最大流最小割切定理及其论证,我们不难得出下面重要结论:设f是网络流图D的一个流,如果存在从源点Z到汇点Z的关于f可增广道路P,那么f一定是最大流。至此,求最大流的基本思路为:标号法(Ford-Fulkerson算法)标号法分为两个过程,一是标号过程,通过标号过程找到一条可增广道路或无法找到可增广道路;二是增广过程,沿可增广道路增加网络流量。从一个可行流出发(若网络中没有初始流,则可以设f是零流)1、标号过程:用V

11、s表示源点,Vt表示汇点。在此过程中,网络中的顶点或者是已标号点(又分为已检查和未检查两种),或者是未标号点。每个标号点的标号包含两部分。第一个标号指明它的标号是从哪个顶点得到的,以便找出可改进量,第二个标号是为确定可改进量而设的。标号过程开始,先给源点Vs标上(0,+),这时Vs是已标号而未检查的点,其余都是未标号点。一般地,取一个已标号而未检查的点Vi,对一切未标号点Vj:若存在弧(Vi,Vj)且fij0,则给Vj标号(-Vi,L(Vj),其中L(Vj)=Min(L(Vi),fji),至此,Vj成为已标号而未检查点。在Vi的全部相邻顶点都已标号后,Vi成为标号而已检查的顶点。重复上述步骤,

12、一旦Vt被标号,表明得到一条从Vs到Vt的可增广道路P,转入增广过程。若所有标号点都已检查过使得标号过程无法继续时,则算法结束,这是的可行流即为最大流。2、增广过程 所得可增广道路P上的顶点都已标号。因此多用“倒向追踪”的方法,从Vt开始,利用标号点的第一个标号可得P上一条边,并以Vt的第二个标号l(Vt)(即可增广流量)作为改进量,增大P上的流量。 具体步骤如下: 取Vt的第一个标号Vk(或-Vk),则弧(Vk,Vt)(或相应的弧(Vt,Vk))是P上的弧,接下来再根据Vk的第一个标号Vi(或-Vi),再找到P上的弧(Vi,Vk)(或(Vk,Vi) ,直到找到Vs为止,这是所有被找出的弧就构

13、成了可增广道路P。 根据第一个标号的正负号,可知其方向是前向还是后向。令改进量=L(Vt),对弧上的流量fij作改进:fij+ (Vi,Vj)为p+fij- (Vi,Vj)为p-Fij= 去掉所有的标号,对新的流F=(fij)重新进入标号过程。求最大流标号发的描述数据结构Const maxn=Type node=record 可增广道路的顶点类型 l,p:integer; 第一标号,检查标号 end; arc=record 网络边类型 c,f:integer; 容量,流量 end; gtype=array0.maxn,0.maxn of arc; 网矩阵 ltype=array0.maxn o

14、f node; 可增广道路var lt:ltype; 可增广道路 g:gtype; 网络 n,s,t:integer; 顶点数,源点,汇点 主要算法1 初始化网络,可增广道路procedure read-graph; var I,j:integer;begin readln(n); 顶点数 fillchar(g,sizeof(g),0); 初始化网络 fillchar(lt,sizeof(lt),0); 初始化可增广道路 for i:=1 to n do for j:=1 to n do read(gI,j.c);end;2 寻找已标号而来检查的顶点序号function check:integ

15、er; var i:integer;begin i:=1; while (i=n)and not(lti.l0)and(lti.p=0) do inc(i); if in then check:=0 顶点不存在 else check:=i;end;3 标号过程,并返回是否找到可增广道路及改进量afunction ford(var a:integer):boolean; 无增广道路返回true var I,j,m,x:integer;begin ford:=true; fillchar(lt,sizeof(lt),0); 去掉原来的标号 lts.l:=s; 从Vs开始 repeat i:=che

16、ck; 寻找一个已标号而未检查的顶点i if i=0 then exit; 若该顶点不存在,则退出过程,返回true for j:=1 to n do if (ltj.l=0)and(gI,j.c0)or(gj,i.c0) 寻找与Vi相邻且未标号的顶点j then begin if (gI,j.f0) then ltj.l:=-I; end; lti.p:=1; 顶点Vi置已检查标志 until (ltt.l0) 直到汇点Vt标号为止 m:=t; a:=maxint; 从Vt倒推,改进量a赋初值 repeat 求a j:=m; m:=abs(ltt.l); if ltj.l0 then x:=

17、gm,j.c-gm,j.f; if ax then a:=x; until m=s; 直至例推到顶点Vs为止 ford:=false; 返回可增广道路存在标志falseend;4 修正流量procedure fulkerson(a:integer); var m,j:integer;begin m:=t; 以顶点Vt出发,逆向沿可增广道路修正容量 repeat j:=m; m:=abs(ltj.l); if ltj.l0 then gm,j.f:=gm,j.f+a; 前向边p+until m=s;end;5 输出所有弧的流量procedure answer; var I,j:integer;b

18、egin for i:=1 to n do for j:=1 to n do writeln(,I, ,j, ), ,gI,j.f)end;6 算法合成procedure proceed; 求最大流var d:integer; success:boolean;begins:=1; t:=n; 假设源点为V1,汇点为Vnrepeatsuccess:=ford(d); 寻找可增广道路及改进量dif success then answer 增广道路不存在,输出最大流 else fulkerson(d) 沿增广道路修正流量until success;end;7 主程序beginread_graph;

19、输入网proceed; 求最大流end.计算最大流的dinic算法 Dinic算法的思想是分阶段地在层次图中改进流量。下面先介绍网络图的剩余图及层次图概念。 剩余图:给定一个网络流图D1=(V1,E1,c)及一可行流f,与该网络流图D1=(V1,E1,c)关于流f的剩余图D2=(V2,E2),D2的顶点集与D1的顶点集相同,即V2=V1。对于D1中的任一条有向边(u,v)E1,若fuv0,那么边(u,v) E2,guv=fuv,显然改变为后向边。由此可见,网络流图D1中的每条边在剩余图D2中都化作了一条或两条边,D2中的每条边都表示在D1中能沿某方向则增广,D2中边(u,v)的权值guv表示在

20、D1中能够沿着Vu到Vv的方向增广大小为guv的流量。见下图。层次图:在剩余图中,把源点到点i的最短路径长度称作点i的层次,记为level(i)。源点s的层次为0。层次图的构造是这样的,设层次图D3=(V3,E3),对于剩余图D2=(V2,E2)中的一条边(u,v),当且仅当level(v)=level(u)+1时,边(u,v)E3,V3=uE3中有边与u相连。 直观地讲,层次图是建立在剩余图基础上的一张“最短路径图”。从源点开始,在层次图中沿着边不管怎么走,经过的路径一定是终点在剩余图中的最短路径。在D2中,从源点vs到汇点vt的任意一条简单路径(即不存在重复顶点或边的路径)都对应可增广路径

21、,路径上每条边的权值的最小值即为能够一次增广的容量。1dinic算法的基本流程算法是循环结构,将每一次循环称为一个阶段,在每个阶段中,首先根据剩余图建立层次图,然后用dfs过程在层次图内扩展可增广路径,调整流量。增广完毕后,进入下一个阶段。这样不断重复,直到汇点不再层次图内出现为止,汇点不再层次图内意味着在剩余图中不存在从源点到汇点的路径,即没有可增广路径。在算法实现中,层次图并不是构建出来的只需在剩余图中对每个顶点标记层次level,增广时,判断边是否满足level(u)+1=level(v)约束即可。2、Dinic算法描述(1)数据结构Const maxn= maxm= maxw=+ 取一

22、个极大数type gtype=record (边类型) x,y,c,f,next,op:longint; 分别为边(x,y),容量,流量,后继指针,反向指针 end;Var g:array1.maxm*2 of gtype; 以边目表存储网络流图 first,first1:array1.maxn of longint; 顶点Vi引出的首条边序号firsti p,level,prt:array1.maxn of longint; 队列或栈p,顶点Vi的层次level,可增广路 径上顶点Vi引出的边序号prti visited:array1.maxn of longint; 访问序列 n,m,to

23、t,vs,vt,maxflow,temp:longint; 顶点数n,边数m,边序号tot,最大流量maxflow构造初始剩余图。 将网络图的边目表,及初始流f=0,通过add(a,b,c)过程插入容量为c的边(a,b)和容量为0的反向边(b,a)。 边目表的存储的链表形式:将顶点Vi引出的所有边存储在一个链表中,首条边的序号为firsti,顺着next指针,依次访问顶点Vi引出的所有边。 过程add。Procedure add(a,b,c:longint); Begin Inc(tot); gtot.x:=a; gtot.y:=b; gtot.c:=0; gtot.next:=first1a

24、; first1a:=tot; 在a顶点引出的边表尾部插入该条边 If firsta=-1 then firsta:=tot; gtot.op:=tot+1; 设置反向边指针 inc(tot); gtot.x:=b; gtot.y:=a; gtot.c:=0; 新增一条容量为0的边(b,a) gtot.next:=first1b; first1b:=tot; 在b顶点引出的边表尾部插入该条边If firstb=-1 then firstb:=tot; gtot.op:=tot-1; 设置反向边指针 end;构建初始剩余图,设f=0为零流。Fillchar(g,sizeof(g),0); 网络流

25、图初始化为空Readln(n,m); 读入顶点数,边数For i:=1 to n do begin 每个顶点引出的边集初始化为空 firsti:=-1; first1:=-1 end; Tot:=0; 边序号初始化For i:=1 to m do 读入第i条边(a,b)及容量c,将该边和反向边插入到g中 Begin Readln(a,b,c); Add(a,b,c); End;通过宽度优先搜索计算顶点层次level。 首先源点进队列,然后按照“层次”搜索剩余图,取出队首元素,搜索剩余图中队首元素引出的所有边。若边的两端点的层次至少相差2层以上,则另一个端点入队,该端点置于队首元素的下一层。依此

26、类推,直至队列空。 Procedure make_level; Var I,open,closed,temp,tp:longint; 队首指针open,队尾指针closed,队首元素tp Begin For i:=1 to n do leveli:=maxw; (每个顶点层次初始化) Fillchar(p,sizeof(p),0); 队列置空 Open:=1; closed:=0; popen:=vs; levelvs:=1; 源点vs进入队列,层次为1 While closedopen do 若队列非空,则取出队首顶点tp Begin Inc(closed); tp:=pclosed; If

27、 tp=vt then exit; 若队首为汇点,则退出 Temp:=firsttp; 搜索剩余图中与队首顶点相连的所有边 While temp-1 do Begin If levelgtemp.yleveltp+1 Then if (gtemp.f0) Then 若当前边属于剩余图,则另一端进入队列,其层次为队首顶点的下一层 Begin Inc(open);popen:=gtemp.y;levelgtemp.y:=leveltp+1; End; Temp:=gtemp.next; 取队首顶点相连的下一条边 End; End; End;执行了make_level过程后,来计算出汇点Vt的层次,

28、(levelVt=maxw),则说明源点Vs与汇点Vt间无路可通,不存在可增广路径,当前流为最大流。在计算出层次图后,则通过dfs扩展可增广路径来调整流量。在层次图内扩展可增广路径,调整流量。使用堆栈存储目前找到的可增广路径,栈顶指针指向路径中的最后一个顶点。一开始,栈中只有源点。Dfs过程分两个操作:如果栈顶元素为汇点,即找到了可增广路径,那么对栈中的可增广路径进行流量调整。流量调整后,栈顶里饱和边对应顶点间的所有元素出栈,以后进需要对栈中余下路径进行增广;如果栈顶元素u非汇点,且栈顶元素在层次图中连出的属于剩余图的边(u,v),则顶点v入栈,可增广路径中又扩展出一条边(u,v),并继续以u引出的下一条边出发进行dfs遍历;若u在

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1