对于网络模型这个专题,以问题为导向,主要探究了如下问题:
1)最短路问题
2)最大流问题
3)最小费用最大流问题
下面,具体分析:
一、最短路问题:
3)Matlab代码:
function [d index1 index2 ] = Dijkf( a )
%Difkstra算法求最短路
%a表示图的权值矩阵
%d表示求得最短路的权和
%index1表示标号顶点顺序
%index2表示标号顶点索引
M=max(max(a));
pb(1:length(a))=0;
pb(1)=1;
index1=1;
index2=ones(1,length(a));
d(1:length(a))=M;
d(1)=0;
temp=1;
while sum(pb)<length(a)
tb=find(pb==0);
d(tb)=min(d(tb),d(temp)+a(temp,tb));
tmpb=find(d(tb)==min(d(tb)));
temp=tb(tmpb(1));
pb(temp)=1;
index1=[index1,temp];
index=index1(find(d(index1)==d(temp)-a(temp,index1)));
if length(index)>=2
index=index(1);
end
index2(temp)=index;
end
d;
index1;
index2;
end
function [ P u ] = f_path( W )
%用Warshall-Floyd算法求最短路
%W表示权值矩阵
%P表示最短路
%u表示最短路的权和
n=length(W);
U=W;
m=1;
while m<=n
for i=1:n
for j=1:n
if U(i,j)>U(i,m)+U(m,j)
U(i,j)=U(i,m)+U(m,j);
end
end
end
m=m+1;
end
u=U(1,n);
P1=zeros(1,n);
k=1;
P1(k)=n;
V=ones(1,n)*inf;
kk=n;
while kk~=1
for i=1:n
V(1,i)=U(1,kk)-W(i,kk);
if V(1,i)==U(1,i)
P1(k+1)=i;
kk=i;
k=k+1;
end
end
end
k=1;
wrow=find(P1~=0);
for j=length(wrow):(-1):1
P(k)=P1(wrow(j));
k=k+1;
end
P;
end
4)应用举例:
M=[0 50 1000 40 25 10
50 0 15 20 1000 25
1000 15 0 10 20 1000
40 20 10 0 10 25
25 1000 20 10 0 55
10 25 1000 25 55 0];
[d index1 index2]=Dijkf(M)
d = 0 35 45 35 25 10
index1 =1 6 5 2 4 3
index2 =1 6 5 6 1 1
a(1,:)=[0 2 8 1 Inf Inf Inf Inf];
a(2,:)=[zeros(1,2) 6 Inf 1 Inf Inf Inf];
a(3,:)=[zeros(1,3) 7 5 1 2 Inf];
a(4,:)=[zeros(1,4) Inf Inf 9 Inf];
a(5,:)=[zeros(1,5) 3 Inf 8];
a(6,:)=[zeros(1,6) 4 6];
a(7,:)=[zeros(1,7) 3];
a(8,:)=zeros(1,8);
a=a+a’;
[ P u ] = f_path( a )
P = 1 2 5 8
u =11
二、最大流问题
1)理论知识:
在生产实践中,把商品从产地v1运往销地vn,这样构成一个交通网,该交通网的每条弧vivj代表从某地vi到vj的运输线,产品经过这条弧由vi运输到vj,并且赋这条运输线的最大通过能力,这样产品经过交通网从v运输到vn。现在要求制定一个运输方案,使得从v1运输带vn的产品数量最多,以上类似问题均统称为网络的最大流问题。
2)算法思路:
Ford-Fulkerson标号算法:
从一个已知流开始,比如零流,递推地构作出一个其值不断增加的流的序列,并且终止于最大流,在每一个新的流f作出之后,若存在f可增路P,则求出,然后作出基于P的修改流f,并且取为这个序列的下一个流,若不存在f可増路,则算法终止。这样最终得出的f就是最大流。
1)标号过程是:
3)MATLAB代码
function [f wf No] = fofuf(C,f1)
%C表示弧上的容量
%f1表示弧上现在的流量函数,默认情况下为0
%f表示最大流
%wf表示最大流量
%No标号函数,由此可得最小割
%待求最大流的源为第一个顶点,汇为最后一个顶点
n=length(C);
if nargin==1
f=zeros(n,n);
else
f=f1;
end
No=zeros(1,n);
d=zeros(1,n);
while(1)
No(1)=n+1;
d(1)=inf;
while(1)
pd=1;
for(i=1:n)
if(No(i))
for(j=1:n)
if(No(j)==0&&f(i,j)<C(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)
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
if(pd)
break;
end
dvt=d(n);
t=n;
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=No(t);
end
end
wf=0;
for j=1:n
wf=wf+f(1,j);
end
f;
wf;
No;
end
4)应用举例:
C=[0 5 4 3 0 0 0 0;0 0 0 0 5 3 0 0;0 0 0 0 0 3 2 0;0 0 0 0 0 0 2 0;0 0 0 0 0 0 0 4;0 0 0 0 0 0 0 3;0 0 0 0 0 0 0 5;0 0 0 0 0 0 0 0];
[f wf No] = fofuf©
f = 0 5 4 2 0 0 0 0
0 0 0 0 4 1 0 0
0 0 0 0 0 2 2 0
0 0 0 0 0 0 2 0
0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 3
0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0
wf = 11
No = 9 0 0 1 0 0 0 0
function [f wf zwf] = BGf(C,b)
%C表示弧容量矩阵
%b表示弧上单位流量的费用
%f表示最小费用最大流矩阵
%wf表示最大流量
%zwf表示最小费用
n=size(C,2);
wf=0;
wf0=inf;
f=zeros(n,n);
while(1)
a=ones(n,n)*inf;
for i=1:n
a(i,i)=0;
end
for i=1:n
for j=1:n
if(C(i,j)>0&&f(i,j)==0)
a(i,j)=b(i,j);
elseif(C(i,j)>0&&f(i,j)==C(i,j))
a(j,i)=-b(i,j);
elseif(C(i,j)>0)
a(i,j)=b(i,j);
a(j,i)=-b(i,j);
end
end
end
for i=2:n
p(i)=inf;
s(i)=i;
end
for k=1:n
pd=1;
for i=2:n
for j=1:n
if(p(i)>p(j)+a(j,i))
p(i)=p(j)+a(j,i);
s(i)=j;
pd=0;
end
end
end
if(pd)
break;
end
end
if(p(n)==inf)
break;
end
dvt=inf;
t=n;
while(1)
if(a(s(t),t)>0)
dvtt=C(s(t),t)-f(s(t),t);
elseif (a(s(t),t))
dvtt=f(t,s(t));
end
if(dvt>dvtt)
dvt=dvtt;
end
if(s(t)==1)
break;
emd
t=s(t);
end
pd=0;
if(wf+dvt>=wf0)
dvt=wf0-wf;
pd=1;
end
t=n;
while(1)
if(a(s(t),t)>0)
f(s(t),t)=f(s(t),t)+dvt;
elseif(a(s(t),t)<0)
f(t,s(t))=f(t,s(t))-dvt;
end
if(s(t)==1)
break;
end
t=s(t);
end
if(pd)
break;
end
wf=0;
for j=1:n
wf=wf+f(1,j);
end
end
zwf=0;
for i=1:n
for j=1:n
zwf=zwf+b(i,j)*f(i,j);
end
end
f;
end
4)应用举例:
C=[0 15 16 0 0;0 0 0 13 14;0 11 0 17 0;0 0 0 0 8;0 0 0 0 0];
b=[0 4 1 0 0;0 0 0 6 1;0 2 0 3 0;0 0 0 0 2;0 0 0 0 0];
[f wf zwf]=BGf(C,b)
f = 0 0 22 0 0
0 0 0 0 14
0 14 0 8 0
0 0 0 0 8
0 0 0 0 0
wf =22
zwf =104
参考文献:
[1]李工农.运筹学基础及其MATLAB应用.北京:清华大学出版社,2016
[2]王健,赵国生.MATLAB数学建模与仿真.北京:清华大学出版社,2016
[3]王海英.图论算法及其MATLAB实现.北京:北京航空航天大学出版社,2010