网络算法汇总含matlab代码_数学建模(十一)

对于网络模型这个专题,以问题为导向,主要探究了如下问题:
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

在这里插入图片描述
3)Matlab代码:

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

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页