M(i,j)=0;end;end
for(i=1:
n)for(j=1:
n)%生成子图Gl
if(L(i,1)+L(j,2)==A(i,j))Gl(i,j)=1;
elseGl(i,j)=0;end;end;end
ii=0;jj=0;
for(i=1:
n)for(j=1:
n)if(Gl(i,j))ii=i;jj=j;break;end;end
if(ii)break;end;end%获得仅含Gl的一条边的初始匹配M
M(ii,jj)=1;
for(i=1:
n)S(i)=0;T(i)=0;NlS(i)=0;end
while
(1)
for(i=1:
n)k=1;
否则.
for(j=1:
n)if(M(i,j))k=0;break;end;end
if(k)break;end;end
if(k==0)break;end%获得最佳匹配M,算法终止
S
(1)=i;jss=1;jst=0;%S={xi},T=φ
while
(1)
jsn=0;
for(i=1:
jss)for(j=1:
n)if(Gl(S(i),j))jsn=jsn+1;NlS(jsn)=j;%NL(S)={v|u∈S,uv∈EL}
for(k=1:
jsn-1)if(NlS(k)==j)jsn=jsn-1;end;end;end;end;end
if(jsn==jst)pd=1;%判断NL(S)=T?
for(j=1:
jsn)if(NlS(j)~=T(j))pd=0;break;end;end;end
if(jsn==jst&pd)al=Inf;%如果NL(S)=T,计算al,Inf为∞
for(i=1:
jss)for(j=1:
n)pd=1;
for(k=1:
jst)if(T(k)==j)pd=0;break;end;end
if(pd&al>L(S(i),1)+L(j,2)-A(S(i),j))al=L(S(i),1)+L(j,2)-A(S(i),j);end;end;end
for(i=1:
jss)L(S(i),1)=L(S(i),1)-al;end%调整可行点标记
for(j=1:
jst)L(T(j),2)=L(T(j),2)+al;end%调整可行点标记
for(i=1:
n)for(j=1:
n)%生成子图GL
if(L(i,1)+L(j,2)==A(i,j))Gl(i,j)=1;
elseGl(i,j)=0;end
M(i,j)=0;k=0;end;end
ii=0;jj=0;
for(i=1:
n)for(j=1:
n)if(Gl(i,j))ii=i;jj=j;break;end;end
if(ii)break;end;end%获得仅含Gl的一条边的初始匹配M
M(ii,jj)=1;break
else%NL(S)≠T
for(j=1:
jsn)pd=1;%取y∈NL(S)\T
for(k=1:
jst)if(T(k)==NlS(j))pd=0;break;end;end
if(pd)jj=j;break;end;end
pd=0;%判断y是否为M的饱和点
for(i=1:
n)if(M(i,NlS(jj)))pd=1;ii=i;break;end;end
if(pd)jss=jss+1;S(jss)=ii;jst=jst+1;T(jst)=NlS(jj);%S=S∪{x},T=T∪{y}
else%获得Gl的一条M-增广路,调整匹配M
for(k=1:
jst)M(S(k),T(k))=1;M(S(k+1),T(k))=0;end
if(jst==0)k=0;end
M(S(k+1),NlS(jj))=1;break;end;end;end;end
MaxZjpp=0;
for(i=1:
n)for(j=1:
n)if(M(i,j))MaxZjpp=MaxZjpp+A(i,j);end;end;end
M%显示最佳匹配M
MaxZjpp%显示最佳匹配M的权,程序结束
从一个可行流f开始,求最大流的Ford--Fulkerson标号算法的基本步骤:
⑴标号过程
①给发点vs以标号(+,+∞),ds=+∞.
②选择一个已标号的点x,对于x的所有未给标号的邻接点y,按下列规则处理:
当yx∈E,且fyx>0时,令dy=min{fyx,dx},并给y以标号(x-,dy).
当xy∈E,且fxy<Cxy时,令dy=min{Cxy-fxy,dx},并给y以标号(x+,dy).
③重复②直到收点vt被标号或不再有点可标号时为止.若vt得到标号,说明存在一条
可增广链,转⑵调整过程;若vt未得到标号,标号过程已无法进行时,说明f已经是最大流.
⑵调整过程
④决定调整量d=dvt,令u=vt.
⑤若u点标号为(v+,du),则以fvu+d代替fvu;若u点标号为(v-,du),则以fvu-d
代替fvu.
⑥若v=vs,则去掉所有标号转⑴重新标号;否则令u=v,转⑤.
算法终止后,令已有标号的点集为S,则割集(S,Sc)为最小割,从而Wf=C(S,Sc).
例1求图6-19所示网络的最大流.
利用Ford--Fulkerson标号法求最大流算法的MATLAB程序代码如下:
n=8;C=[05430000
00005300
00000320
00000020
00000004
00000003
00000005
00000000];%弧容量
for(i=1:
n)for(j=1:
n)f(i,j)=0;end;end%取初始可行流f为零流
for(i=1:
n)No(i)=0;d(i)=0;end%No,d记录标号
图6-19
while
(1)
No
(1)=n+1;d
(1)=Inf;%给发点vs标号
while
(1)pd=1;%标号过程
for(i=1:
n)if(No(i))%选择一个已标号的点vi
for(j=1:
n)if(No(j)==0&f(i,j)No(j)=i;d(j)=C(i,j)-f(i,j);pd=0;
if(d(j)>d(i))d(j)=d(i);end
elseif(No(j)==0&f(j,i)>0)%对于未给标号的点vj,当vjvi为非零流弧时
No(j)=-i;d(j)=f(j,i);pd=0;
if(d(j)>d(i))d(j)=d(i);end;end;end;end;end
if(No(n)|pd)break;end;end%若收点vt得到标号或者无法标号,终止标号过程
if(pd)break;end%vt未得到标号,f已是最大流,算法终止
dvt=d(n);t=n;%进入调整过程,dvt表示调整量
while
(1)
if(No(t)>0)f(No(t),t)=f(No(t),t)+dvt;%前向弧调整
elseif(No(t)<0)f(No(t),t)=f(No(t),t)-dvt;end%后向弧调整
if(No(t)==1)for(i=1:
n)No(i)=0;d(i)=0;end;break;end%当t的标号为vs时,终止调整过程
t=No(t);end;end;%继续调整前一段弧上的流f
wf=0;for(j=1:
n)wf=wf+f(1,j);end%计算最大流量
f%显示最大流
wf%显示最大流量
No%显示标号,由此可得最小割,程序结束
设网络G=(V,E,C),取初始可行流f为零流,求解最小费用流问题的迭代步骤:
①构造有向赋权图Gf=(V,Ef,F),对于任意的vivj∈E,Ef,F的定义如下:
当fij=0时,vivj∈Ef,F(vivj)=bij;
当fij=Cij时,vjvi∈Ef,F(vjvi)=-bij;
当0<fij<Cij时,vivj∈Ef,F(vivj)=bij,vjvi∈Ef,F(vjvi)=-bij.
转向②.
②求出有向赋权图Gf=(V,Ef,F)中发点vs到收点vt的最短路m,若最短路m存在转向
③;否则f是所求的最小费用最大流,停止.
③增流.同求最大流的方法一样,重述如下:
令
.
-
+
∈
∈
⎪⎩
⎪⎨⎧
-
=
m
m
d
ij
ij
ij
ijij
ijvv
vv
f
Cf
d=min{dij|vivj∈m},重新定义流f={fij}为
fij=,
-
+
∈
∈
⎪⎩
⎪⎨
⎧
-
+
m
m
d
d
ij
ij
ij
ij
ij
vv
vv
f
f
f
如果Wf大于或等于预定的流量值,则适当减少d值,使Wf等于预定的流量值,那么f是所
求的最小费用流,停止;否则转向①.
求解含有负权的有向赋权图G=(V,E,F)中某一点到其它各点最短路的Ford算法.
当vivj∈E时记wij=F(vivj),否则取wii=0,wij=+∞(i≠j).v1到vi的最短路长记为p(i),
v1到vi的最短路中vi的前一个点记为q(i).Ford算法的迭代步骤:
①赋初值p
(1)=0,p(i)=+∞,q(i)=i,i=2,3,⋯,n.
②更新p(i),q(i).对于i=2,3,⋯,n和j=1,2,⋯,n,如果p(i)<p(j)+wji,则令
p(i)=p(j),q(i)=j.
③终止判断:
若所有的p(i)都无变化,停止;否则转向②.
在算法的每一步中,p(i)都是从v1到vi的最短路长度的上界.若不存在负长回路,则从
v1到vi的最短路长度是p(i)的下界,经过n-1次迭代后p(