数学建模——图论模型

369 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

图论模型-dijkstra算法


Dijkstra算法能求一个顶点到另一顶点最短路径

Dijkstra算法是一种标号法:给赋权图的每一个顶点记一个数,称为顶点的标号(临时标号,称T标号,或者固定标号,称为P标号)。

T标号表示从始顶点到该标点的最短路长的上界;

P标号则是从始顶点到该顶点的最短路长。

算法步骤:

image.png

例:

image.png

image.png

黄色框内数字为距V1点最近路程👆

image.png

到达V11点最近路程经过节点的顺序👆

带权邻接矩阵

表示顶点之间相邻关系的矩阵。

image.png

Inf为没有直接连接,数字为距离

代码:

weight=    [0     2     8     1   Inf   Inf   Inf   Inf   Inf   Inf   Inf;                    2     0     6   Inf     1   Inf   Inf   Inf   Inf   Inf   Inf;                    8     6     0     7     5     1     2   Inf   Inf   Inf   Inf;                    1   Inf     7     0   Inf   Inf     9   Inf   Inf   Inf   Inf;                  Inf     1     5   Inf     0     3   Inf     2     9   Inf   Inf;                  Inf   Inf     1   Inf     3     0     4   Inf     6   Inf   Inf;                  Inf   Inf     2     9   Inf     4     0   Inf     3     1   Inf;                  Inf   Inf   Inf   Inf     2   Inf   Inf     0     7   Inf     9;                  Inf   Inf   Inf   Inf     9     6     3     7     0     1     2;                  Inf   Inf   Inf   Inf   Inf   Inf     1   Inf     1     0     4;                  Inf   Inf   Inf   Inf   Inf   Inf   Inf     9     2     4     0;];
        [dis, path]=dijkstra(weight,1, 11)
        
        
        dijkstra.m
        function [min,path]=dijkstra(w,start,terminal)
        n=size(w,1); label(start)=0; f(start)=start;
        for i=1:n
           if i~=start
               label(i)=inf;
        end, end
        s(1)=start; u=start;
        while length(s)<n
           for i=1:n
              ins=0;
              for j=1:length(s)
                 if i==s(j)
                    ins=1;
                 end,  
              end
              if ins==0
                 v=i;
                 if label(v)>(label(u)+w(u,v))
                    label(v)=(label(u)+w(u,v)); 
                 f(v)=u;
                 end, 
              end, 
           end   
        v1=0;
           k=inf;
           for i=1:n
                 ins=0;
                 for j=1:length(s)
                    if i==s(j)
                       ins=1;
                    end, 
                 end
                 if ins==0
                    v=i;
                    if k>label(v)
                       k=label(v);  v1=v;
                    end,  
                 end,  
           end
           s(length(s)+1)=v1;  
           u=v1;
        end
        min=label(terminal); path(1)=terminal;
        i=1; 
        while path(i)~=start
              path(i+1)=f(path(i));
              i=i+1 ;
        end
        path(i)=start;
        L=length(path);
        path=path(L:-1:1);
        
        

图论模型-Floyd算法


引例:

某公司再六个城市C1,C2,C3,C4,C5,C6都有分公司,公司成员经常往来于它们之间,已知从Ci到Cj的直达航班票价由下述矩阵的第i行,第j列元素给出(∞表示无直达航班),该公司想算出一张任意两个城市之间的最廉价路线航费表。

image.png

算法思想

算法思想原理:

Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从i点到j点的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

从任意节点i到任意节点j的最短路径不外乎2种可能:

  1. 直接从i到j
  2. 从i经过若干个节点k到j

 

所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j) 是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j) ,这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

代码:

a= [ 0,50,inf,40,25,10;
             50,0,15,20,inf,25;
             inf,15,0,10,20,inf;
             40,20,10,0,10,25;
             25,inf,20,10,0,55;
             10,25,inf,25,55,0];
        [D, path]=floyd(a)
        
        floyd.m
        function [D,path,min1,path1]=floyd(a,start,terminal)
        D=a;n=size(D,1);path=zeros(n,n);
        for i=1:n
           for j=1:n
              if D(i,j)~=inf
                 path(i,j)=j;
              end, 
           end,
        end
        for k=1:n
           for i=1:n
              for j=1:n
                 if D(i,k)+D(k,j)<D(i,j)
                    D(i,j)=D(i,k)+D(k,j);
                    path(i,j)=path(i,k);
                 end, 
              end, 
           end,
        end
        if nargin==3
           min1=D(start,terminal);
           m(1)=start;
           i=1;
           path1=[ ];   
           while   path(m(i),terminal)~=terminal
              k=i+1;                                
              m(k)=path(m(i),terminal);
              i=i+1;
           end
           m(i+1)=terminal;
           path1=m;
        end   
        
        

例题输出结果:

image.png

path中的值为下标ij表示的两点之间需经过的点

经验:

在一道题目中,最好使用多种算法进行计算,使论文更严谨,更有说服力。