网络流基础及应用Word格式文档下载.docx

上传人:b****5 文档编号:21452434 上传时间:2023-01-30 格式:DOCX 页数:20 大小:137.25KB
下载 相关 举报
网络流基础及应用Word格式文档下载.docx_第1页
第1页 / 共20页
网络流基础及应用Word格式文档下载.docx_第2页
第2页 / 共20页
网络流基础及应用Word格式文档下载.docx_第3页
第3页 / 共20页
网络流基础及应用Word格式文档下载.docx_第4页
第4页 / 共20页
网络流基础及应用Word格式文档下载.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

网络流基础及应用Word格式文档下载.docx

《网络流基础及应用Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《网络流基础及应用Word格式文档下载.docx(20页珍藏版)》请在冰豆网上搜索。

网络流基础及应用Word格式文档下载.docx

①当所有fij=0,称为零流,零流一定是可行流。

②对于源Z和汇Z’有

∑fZj=∑fjZ’=ω

数ω叫做网络流的流量。

③当fij=Cij时,称边(Vi,Vj)饱和,表示流f对于该边饱和。

④ω达到最大值时的流f,称为D=(V,E,C)的最大流。

三.求最大流的理论基础

1、割切概念——某些边的集合

⑴设D=(V,E,C)是已知的网络流图,假定S是V的一个子集,且S满足

①Z∈S②Z’(not∈)S

且令S’为S的补集,这样把顶点集V分成S和S’两个部分,其中

Z∈S,Z’∈S’

对于一个端点在S,而另一个端点在S’的所有边的集合,叫做网络流图D的一个割切,用(S,S’)表示。

下图用虚线划去的表示一个割切,其中S={Z,b,c,d},S’={a,Z’}。

<

图片>

⑵割切容量C(S,S’):

在割切(S,S’)中,把从S到S’的边容量和叫做这割切的容量。

上边割切容量C(S,S’)=CZa+Cba+CbZ’+CdZ’=4+3+2+4=13

2、定理:

对于已知的网络流,从源点Z到汇点Z’的流量ω的最大值小于等于任何一个割切的容量,即Maxω<

=MinC(S,S’)。

证明:

当Vi为网络流图的任一中间点时,根据平衡条件,恒有

∑fij-∑fji=0⑴

当i=Z时,∑fZj=ω⑵

设(S,S’)为一任一个切,则有

∑(fij-fji)=ω

注:

∵i∈S,Z’(not∈)S,Z∈S

当i≠Z时,由⑴式得0

当i=Z时,由⑵式得ω

又因为S∪S’=V

所以∑(fij-fji)=∑(fij-fji)+∑(fij-fji)=ω⑶

⑶式中∑(fij-fji)的两个下标都是对S的全体求和,其展开式中任意一项fpq都一一对应一项-fpq,所以∑(fij-fji)=0

即由⑶式得∑(fij-fji)=ω⑷

再由于0<

Cij,所以fij-fji<

=Cij

由⑷式ω=∑(fij-fji)<

=∑Cij=C(S,S’)

故有Maxω<

=MinC(S,S’)

3、最大流量最小割切定理(Ford-Fulkerson定理)

在一个给定的网络流图上,流的极大值等于割切容量的最小值,即

Maxω=MinC(S,S’)

(下面的证明是构造性的,可以从中引出求最大流的算法思想)

(求证思路:

由于已知Maxω<

=MinC(S,S’)是不能进一步增加流量,直到使Maxω=MinC(S,S’))

在网络流图D=(V,E,C)中,定义从源点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+若fij<

Cij,P-有fij>

0,则称这条路为可增广道路。

修改可增广道路上每条边的流量,同时保持网络流的可行性,达到流量的增加,其增量的确定方法如下:

Cij-fijP+

fijP-

令δij={

取δ=Min(δij),为增量。

就是对可增广道路P的每一条前向边流量增加δ,每一条后向边流量减少δ,从而使得整个网络流的流量获得增加(这是显而易见的)

下面论证Maxω=MinC(S,S’)

设网络流图D的流量f达到极大,我们构造一个割切(S,S’)如下

若Z’∈S,则有一条从Z到Z’的道路,Z=V0,V1,...,Vk=Z’,这条道路上所有的边均不饱和,因而是条可增广道路,这和f是最大流的假设矛盾。

①Z∈S

②若x∈S,且fxy<

Cxy,则y∈S

若x∈S,且fyx>

0,则y∈S

显然Z’∈S’(Z’的出度d(Z’)=0),

所以(S,S’)是一个割切。

按照子集S的定义,若x∈S,y∈S’,则fxy=Cxy

若y∈S’,x∈S,则fyx=0

所以ω=∑(fxy-fyx)=∑fxy=∑C(S,S’)

即Maxω=MinC(S,S’)

通过以上论证,可知

①当D中找不到可增广道路时,此时的流为最大流;

②当D中的流最大时,一定存在容量最小的割切(S,S’)

四.求网络最大流的算法

根据上述最大流最小割切定理及其论证,我们不难得出下面重要结论:

设f是网络流图D的一个流,如果存在从源点Z到汇点Z’的关于f可增广道路P,那么f一定是最大流。

至此,求最大流的基本思路为:

㈠标号法(Ford-Fulkerson算法)

标号法分为两个过程,一是标号过程,通过标号过程找到一条可增广道路或无法找到可增广道路;

二是增广过程,沿可增广道路增加网络流量。

从一个可行流出发(若网络中没有初始流,则可以设f是零流)

1、标号过程:

用Vs表示源点,Vt表示汇点。

在此过程中,网络中的顶点或者是已标号点(又分为已检查和未检查两种),或者是未标号点。

每个标号点的标号包含两部分。

第一个标号指明它的标号是从哪个顶点得到的,以便找出可改进量,第二个标号是为确定可改进量δ而设的。

标号过程开始,先给源点Vs标上(0,+∞),这时Vs是已标号而未检查的点,其余都是未标号点。

一般地,取一个已标号而未检查的点Vi,对一切未标号点Vj:

⑴若存在弧(Vi,Vj)且fij<

Cij,则给Vj标号(Vi,L(Vj)),其中L(Vj)=Min(L(Vi),Cij-fij);

⑵若存在弧(Vj,Vi)且fji>

0,则给Vj标号(-Vi,L(Vj)),其中L(Vj)=Min(L(Vi),fji),

至此,Vj成为已标号而未检查点。

在Vi的全部相邻顶点都已标号后,Vi成为标号而已检查的顶点。

重复上述步骤,一旦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为止,这是所有被找出的弧就构成了可增广道路P。

根据第一个标号的正负号,可知其方向是前向还是后向。

令改进量δ=L(Vt),对弧上的流量fij作改进:

fij+δ(Vi,Vj)为p+

fij-δ(Vi,Vj)为p-

Fij’=

②去掉所有的标号,对新的流F’=(fij’)重新进入标号过程。

求最大流标号发的描述

⑴数据结构

Constmaxn=<

网络顶点数>

Typenode=record{可增广道路的顶点类型}

l,p:

integer;

{第一标号,检查标号}

end;

arc=record{网络边类型}

c,f:

integer;

{容量,流量}

gtype=array[0..maxn,0..maxn]ofarc;

{网矩阵}

ltype=array[0..maxn]ofnode;

{可增广道路}

varlt:

ltype;

g:

gtype;

{网络}

n,s,t:

{顶点数,源点,汇点}

⑵主要算法

1初始化网络,可增广道路

procedureread-graph;

varI,j:

begin

readln(n);

{顶点数}

fillchar(g,sizeof(g),0);

{初始化网络}

fillchar(lt,sizeof(lt),0);

{初始化可增广道路}

fori:

=1tondo

forj:

read(g[I,j].c);

end;

2寻找已标号而来检查的顶点序号

functioncheck:

vari:

i:

=1;

while(i<

=n)andnot((lt[i].l<

>

0)and(lt[i].p=0))doinc(i);

ifi>

nthencheck:

=0{顶点不存在}

elsecheck:

=i;

3标号过程,并返回是否找到可增广道路及改进量a

functionford(vara:

integer):

boolean;

{无增广道路返回true}

varI,j,m,x:

ford:

=true;

{去掉原来的标号}

lt[s].l:

=s;

{从Vs开始}

repeat

=check;

{寻找一个已标号而未检查的顶点i}

ifi=0thenexit;

{若该顶点不存在,则退出过程,返回true}

if(lt[j].l=0)and((g[I,j].c<

0)or(g[j,i].c<

0)

{寻找与Vi相邻且未标号的顶点j}

thenbegin

if(g[I,j].f<

g[I,j].c)thenlt[j].l:

=I;

if(g[j,i].f>

0)thenlt[j].l:

=-I;

end;

lt[i].p:

{顶点Vi置已检查标志}

until(lt[t].l<

0){直到汇点Vt标号为止}

m:

=t;

a:

=maxint;

{从Vt倒推,改进量a赋初值}

repeat{求a}

j:

=m;

=abs(lt[t].l);

iflt[j].l<

0thenx:

=g[j,m].f;

iflt[j].l>

=g[m,j].c-g[m,j].f;

ifa>

xthena:

=x;

untilm=s;

{直至例推到顶点Vs为止}

=false;

{返回可增广道路存在标志false}

4修正流量

procedurefulkerson(a:

integer);

varm,j:

{以顶点Vt出发,逆向沿可增广道路修正容量}

=abs(lt[j].l);

0theng[j,m].f:

=g[j,m].f-a;

{后向边p-}

0theng[m,j].f:

=g[m,j].f+a;

{前向边p+}

untilm=s;

5输出所有弧的流量

procedureanswer;

writeln(‘(’,I,‘,’,j,‘)’,‘’,g[I,j].f)

6算法合成

procedureproceed;

{求最大流}

vard:

success:

s:

t:

=n;

{假设源点为V1,汇点为Vn}

repeat

success:

=ford(d);

{寻找可增广道路及改进量d}

ifsuccessthenanswer{增广道路不存在,输出最大流}

elsefulkerson(d){沿增广道路修正流量}

untilsuccess;

7主程序

read_graph;

{输入网}

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,若fuv<

cuv,那么边(u,v)∈E2,并置这条边在D2中的权值为guv=cuv-fuv,显然该边为前向边。

若fuv>

0,那么边(u,v)∈E2,…………guv=fuv,显然改变为后向边。

由此可见,网络流图D1中的每条边在剩余图D2中都化作了一条或两条边,D2中的每条边都表示在D1中能沿某方向则增广,D2中边(u,v)的权值guv表示在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={u∣E3中有边与u相连}。

直观地讲,层次图是建立在剩余图基础上的一张“最短路径图”。

从源点开始,在层次图中沿着边不管怎么走,经过的路径一定是终点在剩余图中的最短路径。

在D2中,从源点vs到汇点vt的任意一条简单路径(即不存在重复顶点或边的路径)都对应可增广路径,路径上每条边的权值的最小值即为能够一次增广的容量。

1.dinic算法的基本流程

算法是循环结构,将每一次循环称为一个阶段,在每个阶段中,首先根据剩余图建立层次图,然后用dfs过程在层次图内扩展可增广路径,调整流量。

增广完毕后,进入下一个阶段。

这样不断重复,直到汇点不再层次图内出现为止,汇点不再层次图内意味着在剩余图中不存在从源点到汇点的路径,即没有可增广路径。

在算法实现中,层次图并不是构建出来的只需在剩余图中对每个顶点标记层次level,增广时,判断边是否满足level(u)+1=level(v)约束即可。

2、Dinic算法描述

(1)数据结构

顶点数上限>

maxm=<

边数上限>

maxw=+∞{取一个极大数}

type

gtype=record(边类型)

x,y,c,f,next,op:

longint;

{分别为边(x,y),容量,流量,后继指针,反向指针}

Var

g:

array[1..maxm*2]ofgtype;

{以边目表存储网络流图}

first,first1:

array[1..maxn]oflongint;

{顶点Vi引出的首条边序号first[i]}

p,level,prt:

{队列或栈p,顶点Vi的层次level,可增广路

径上顶点Vi引出的边序号prt[i]}

visited:

{访问序列}

n,m,tot,vs,vt,maxflow,temp:

{顶点数n,边数m,边序号tot,最大流量maxflow}

⑵构造初始剩余图。

将网络图的边目表,及初始流f=0,通过add(a,b,c)过程插入容量为c的边(a,b)和容量为0的反向边(b,a)。

边目表的存储的链表形式:

将顶点Vi引出的所有边存储在一个链表中,首条边的序号为first[i],顺着next指针,依次访问顶点Vi引出的所有边。

过程add。

Procedureadd(a,b,c:

longint);

Begin

Inc(tot);

g[tot].x:

=a;

g[tot].y:

=b;

g[tot].c:

=0;

g[tot].next:

=first1[a];

first1[a]:

=tot;

{在a顶点引出的边表尾部插入该条边}

Iffirst[a]=-1thenfirst[a]:

g[tot].op:

=tot+1;

{设置反向边指针}

inc(tot);

{新增一条容量为0的边(b,a)}

=first1[b];

first1[b]:

{在b顶点引出的边表尾部插入该条边}

Iffirst[b]=-1thenfirst[b]:

=tot-1;

构建初始剩余图,设f=0为零流。

Fillchar(g,sizeof(g),0);

{网络流图初始化为空}

Readln(n,m);

{读入顶点数,边数}

Fori:

=1tondobegin{每个顶点引出的边集初始化为空}

first[i]:

=-1;

first1:

=-1

Tot:

{边序号初始化}

=1tomdo{读入第i条边(a,b)及容量c,将该边和反向边插入到g中}

Readln(a,b,c);

Add(a,b,c);

End;

⑶通过宽度优先搜索计算顶点层次level。

首先源点进队列,然后按照“层次”搜索剩余图,取出队首元素,搜索剩余图中队首元素引出的所有边。

若边的两端点的层次至少相差2层以上,则另一个端点入队,该端点置于队首元素的下一层。

依此类推,直至队列空。

Proceduremake_level;

VarI,open,closed,temp,tp:

{队首指针open,队尾指针closed,队首元素tp}

Begin

Fori:

=1tondolevel[i]:

=maxw;

(每个顶点层次初始化)

Fillchar(p,sizeof(p),0);

{队列置空}

Open:

closed:

p[open]:

=vs;

level[vs]:

{源点vs进入队列,层次为1}

Whileclosed<

opendo{若队列非空,则取出队首顶点tp}

Begin

Inc(closed);

tp:

=p[closed];

Iftp=vtthenexit;

{若队首为汇点,则退出}

Temp:

=first[tp];

{搜索剩余图中与队首顶点相连的所有边}

Whiletemp<

-1do

Begin

Iflevel[g[temp].y]>

level[tp]+1

Thenif(g[temp].f<

g[temp].c)or((g[temp].c=0)and(g[temp].f>

0))

Then

{若当前边属于剩余图,则另一端进入队列,其层次为队首顶点的下一层}

Inc(open);

p[open]:

=g[temp].y;

level[g[temp].y]:

=level[tp]+1;

Temp:

=g[temp].next;

{取队首顶点相连的下一条边}

执行了make_level过程后,来计算出汇点Vt的层次,(level[Vt]=maxw),则说明源点Vs与汇点Vt间无路可通,不存在可增广路径,当前流为最大流。

在计算出层次图后,则通过dfs扩展可增广路径来调整流量。

⑷在层次图内扩展可增广路径,调整流量。

使用堆栈存储目前找到的可增广路径,栈顶指针指向路径中的最后一个顶点。

一开始,栈中只有源点。

Dfs过程分两个操作:

①如果栈顶元素为汇点,即找到了可增广路径,那么对栈中的可增广路径进行流量调整。

流量调整后,栈顶里饱和边对应顶点间的所有元素出栈,以后进需要对栈中余下路径进行增广;

②如果栈顶元素u非汇点,且栈顶元素在层次图中连出的属于剩余图的边(u,v),则顶点v入栈,可增广路径中又扩展出一条边(u,v),并继续以u引出的下一条边出发进行dfs遍历;

若u在

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 数学

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

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