数学建模之图论——图与网络模型(一)(基本概念和最短路问题,附MATLAB源码)

图与网络的基本概念与数据结构

一.图与网络的基本概念

图论中图是由点和边构成的,可以反映一些对象之间的关系。
在这里插入图片描述

无向图

无向图(简称图):没有方向,由点和边构成的图,记做G =(V , E),点是V,边是E。
:图论的图与几何图、工程图不一样。
因为一般情况下的图中点的相对位置及点间连线长短,对于反映对象之间的关系并不是重要的。

联结 v i 1 v_i{_1} v i k v_{ik} 的链:在无向图G中,若存在一个点边的交错序列( v i 1 , e i 1 , v i 2 , e i 2 , . . . v i k 1 , e i k 1 , c i k v_{i1},e_{i1},v_{i2},e_{i2},...v_{i_{k-1}},e_{i_{k-1}},c_{ik} )其中 v i k v_{ik} 属于V(G), e i j e_{ij} 属于E(G)

联结 v_{i1} 和 v_{ik} 的圈:在上述的链中,若 v_{i1} = v_{ik},也就是首尾相连。

连通图:对于一个无向图,若任何两个不同的点之间,至少存在一条链。

简单图:一个图如果它既没有环也没有平行边(两条边连接同一对顶点),称为简单图(simple graph)。
在这里插入图片描述
完全图:其中每对不同的顶点之间都恰连有一条边相连
在这里插入图片描述
赋权图:对无向图的每一条边( v i , v j v_i,v_j ) ,都有一个数(称为权重) w i j w_{ij} 对应。

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图
在这里插入图片描述
顶点的度:与顶点v关联的边的个数称为顶点v 的
度(degree) (环计两度),记作 d(v) .
度为零的点称为弧立点,度为1的点称为悬挂点。悬挂点的关联边称为悬挂边。度为奇数的点称为奇点(odd point) ,度为偶数的点称为偶点(even point) 。

有向图

有向图:由点和弧构成的图,记做D =(V , A),其中V是图D的点集,A是图D的弧集。
:无向图是一种特殊的有向图,无向图的边实际上就是等 价于两条方向相反的弧。
联结 v i 1 v_i{_1} v i k v_{ik} 的路:在无向图G中,若存在一个点边的交错序列( v i 1 , e i 1 , v i 2 , e i 2 , . . . v i k 1 , e i k 1 , c i k v_{i1},e_{i1},v_{i2},e_{i2},...v_{i_{k-1}},e_{i_{k-1}},c_{ik} )其中 v i k v_{ik} 属于V(D), e i j e_{ij} 属于V(D)
*联结 v_{i1} 和 v_{ik} 的回路:在上述的链中,若 v_{i1} = v_{ik},也就是首尾相连。
赋权图:对无向图的每一条弧( v i , v j v_i,v_j ) ,都有一个数(称为权重) c i j c_{ij} 对应。
网络:在赋权的有向图D中指定一点为发点(记为 v s v_s ),指定另一点为收点(记为 v t v_t ),其余的点为中间点,并把 D 中的每一条弧的赋权数 c i j c_ij 称为弧 ( v i , v j ) (v_i,v_j) 的容量 ,这样的赋权有向图 D 就称为网络。

二.图与网络的数据结构

描述图与网络的3种常用表示方法:邻接矩阵表示法、关联矩阵表示法、弧表表示法

邻接矩阵表示法

邻接矩阵表示法是将图以邻接矩阵(adjacency matrix)的形式存储在计算机中。图 G=(V,A) 的邻接矩阵是如下定义的:C是一个 n n n*n 的0-1矩阵,即
在这里插入图片描述在这里插入图片描述
也就是说,如果两节点之间有一条弧,则邻接矩阵中对应的元素为1;否则为0。

例一:对于下图,可以用邻接矩阵表示为
在这里插入图片描述
解释:现在有五个图,邻接矩阵a就是 5 5 5*5 的方阵,∵ 1→2,∴a[1][2]=1;
∵1→3所以a[1][3]=1;∵ 4→3,∴a[4][3]=1,其他都是一样的,所有的都写出来就是:在这里插入图片描述
同样,对于网络中的权,也可以用类似邻接矩阵的矩阵表示。只是此时一条弧所对应的元素不再是1,而是相应的权而已。如果网络中每条 弧赋有多种权,则可以用多个矩阵表示这些权。

关联矩阵表示法

关联矩阵表示法是将图以关联矩阵(incidence matrix)的形式存储在计算机中.
B = ( b i k ) n m ( 1 , 0 , 1 ) n m B=(b_{ik})_{n*m}\in({-1 ,0 ,1}) ^{n*m} 的关联矩阵B是如下定义的:B是一个n*m的矩阵,即
在这里插入图片描述

如果一个顶点是一条弧的起点,则关联矩阵中对应的元素为1;如果一个顶点是一条弧的终点,则关联矩阵中对应的元素为-1;如果一个顶点与一条弧不关联,则关联矩阵中对应的元素为0。

例2 对于例1所示的图,如果关联矩阵中每列对应弧的顺序为 (1,2),(1,3),(2,4),(3,2),(4,3),(4,5),(5,3)和(5,4),则关联矩阵表示为(列单位为弧)在这里插入图片描述
这个图有4个节点,7条连线,所以是 4 7 4*7 的矩阵,每一列都是只有一个1,一个 -1。
看e1这条线,头是v1尾是v2,所以v1=1,v2=-1
e3,头是v3,尾是v4,所以v3是1,v4是-1;
在这里插入图片描述)

弧表表示法

弧表表示法将图以弧表(arc list)的形式存储在计算机中。所谓图的弧表,也就是图的弧集合中的所有有序对。
假设例1中的弧(1,2),(1,3),(2,4),(3,2),(4,3),(4,5),(5,3)和(5,4)上的权分别为8,9,6,4,0,3,6和7,则弧表表示如下:
在这里插入图片描述

最短路问题 (Shortest Path Problem)

最短路问题:对一个赋权有向图中指定的两个点 v s v_s v t v_t 找到条从 v s v_s v t v_t 的路,使得这条路上所有弧的权数总和最小,这条路被称为从 v s v_s v t v_t , 的最短路,这条路_上所有弧的权数的总和被称为从 v s v_s v t v_t 的距离。
在这里插入图片描述

Dijkstra算法

如上图,带权值的最短路径长度就是黄线标出来的 为7
求解最短路的迪克斯特拉Dijkstra算法(双标号法)
双标号即:对图中的点 v j v_j 赋予两个标号 ( l j , k j ) (l_j,k_j) ,其中 l_j 表示从起点 v s v_s v j v_j 的最短路的长度, k j k_j 表示在 v s v_s v j v_j 的最短路上前面一个邻点的下标,从而找到所求的最短路及其距离。

D i j k s t r a {\mathbb{\color{Red}下面给出Dijkstra算法的基本步骤:}}

  1. 先给起点 v s v_s 标号:(0,s),表示从 v s v_s v s v_s 的距离为0, v s v_s 为起点。
  2. 找出已标号的点集 I ,未标号的点集 J 以及从 I 到 J 的弧集。
  3. 若上述弧集是空集,则计算结束。此时,如果 v t v_t 已标号 (l_t,k_t) 则 v s v_s v t v_t 的距离为 l t l_t ,而从 v s v_s v t v_t 的最短路,可以从 k t k_t 反向追踪到起点 v s v_s 而得到。 如果 v t v_t 未标号,则不存在从 v s v_s v t v_t 的有向路。 若上述弧集不是空集,则转下一步。
  4. 对上述弧集中的每一条弧,计算 s i j = l i + c i j s_{ij}=l_i+c_{ij} 在所有的 s i j s_{ij} 中,找值最小的弧,不妨设为 ( v c , v a ) (v_c,v_a) 则给此弧的终点 v a v_a 标号 ( s c d , c ) (s_cd,c) ,返回步骤2.

在这里插入图片描述 在这里插入图片描述在这里插入图片描述

在这里插入图片描述1. 先给起点    标号:(0,1),表示从    到     的距离为0, 为起点。

标号(m,n)m是权重,n是前一个节点

在这里插入图片描述
同时,我们可以从各点的标号得到起点到该点的最短路径及距离。
在这里插入图片描述 在这里插入图片描述
在这里插入图片描述 在这里插入图片描述
在这里插入图片描述
用行向量pb表示P标号信息,index1表示标号顶点顺序, index2表示标号顶点索引,d表示最短路的值.

clc,clear
a=zeros(6); %邻接矩阵初始化
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25;
a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25;
a(5,6)=55;
a=a+a';
a(a==0)=inf;
pb(1:length(a))=0;pb(1)=1;index1=1;index2=ones(1,length(a));
d(1:length(a))=inf;d(1)=0;
temp=1; %最新的P标号的顶点
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];
   temp2=find(d(index1)==d(temp)-a(temp,index1));
   index2(temp)=index1(temp2(1));
end
d, index1, index2

程序过程就不具体分析了,只看看输出吧。
d代表距离,在这个题里代表票价,代表c1分别到c1,c2,c3,c4,c5,c6的距离
index1代表标号顺序
index2代表该标号的前一个标号

d =
    0    35    45    35    25    10
index1 =
     1     6     5     2     4     3
index2 =
     1     6     5     6     1     1

第一个标号的是自身c1,不用管,从第二个开始c1→c6,可以看到c6的前一个节点是1,所以c1直接到了c6.距离d=10;
第三个是c5,也是c1直接到的,距离d=25;
第四个c2,可以看到c2的前一个节点是c6,c6的前一个节点是c1,所以c1到c2的最短距离为c1先到c6再从c6到c2,距离为40
其他的以此类推
在这里插入图片描述

Floyd算法

主要用来计算每对顶点之间的最短路径。
Dijkstra算法用来计算一对顶点之间的最短路径。

Floyd算法的基本思想是:递推产生一个矩阵序列 A 0 , A 1 . . . A k . . . A n A_0,A_1...A_k...A_n ,其中 A k ( i , j ) A_k(i,j) 表示从顶点 v i v_i 到顶点 v j v_j 的路径上所经过的顶点序号不大于k的最
短路径度。迭代公式为:
在这里插入图片描述
k是迭代次数, i , j , k = 1 2 3 . . . n i,j,k=1 ,2,3,...n 最后,当k=n时, 即是各顶点之间的最短通路值。
这个算法要产生两个矩阵
这个算法就是找一个中间点,通过判断两个顶点的直接距离与通过中间点的简介距离的远近比较(近的为优) 来不断对两个矩阵进行更新。

在这里插入图片描述
在这里插入图片描述
A代表每两个点之间的距离,path是每两个点之间的最短路径经过的中间点,一开始没有中间点,所以设置为-1,代表没有中间点。
在这里插入图片描述在这里插入图片描述
这个是找一个中间点,一般是从0开始,再找1 2 3,这样过一遍。
在这里插入图片描述
我们直接用1开始吧,因为我算了,0没有更新。
算自身和自身都是0没啥意思,两两连接就是这12对顶点。
{0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 2}, {1, 3),
{2, 0}, {2, 1}, {2, 3}, {3, 0}, {3, 1}, {3, 2}

  • {0,1}:因为要经过1,所以可以看成是 A [ 0 ] [ 1 ] = A [ 0 ] [ 1 ] + A [ 1 ] [ 1 ] A[0][1]=A[0][1]+A[1][1] ,左右相等,不更新
  • {0,2}: A [ 0 ] [ 2 ] > A [ 0 ] [ 1 ] + A [ 1 ] [ 2 ] > 5 + 4 A[0][2]>A[0][1]+A[1][2] \rightarrow \infin >5+4 所以更新,Path矩阵的A[0][2]更新为1(因为中间点是1)A矩阵中的A[0][2]更新为9
  • 这是经过中间点为1跟新后的两个新矩阵
    在这里插入图片描述
  • {0,3}: A [ 0 ] [ 3 ] > A [ 0 ] [ 1 ] + A [ 1 ] [ 3 ] 7 = 5 + 2 A[0][3]>A[0][1]+A[1][3] \rightarrow 7 =5+2 不更新
  • {1,2}{1,3}{1,0}都经过1,不更新,剩下的自己算吧,当然我算了,没有更新。

再以顶点2为中间点进行检测

  • {0,1}: A [ 0 ] [ 1 ] < A [ 0 ] [ 2 ] + A [ 2 ] [ 1 ] 5 < 9 + 3 A[0][1]<A[0][2]+A[2][1] \rightarrow 5<9+3 不更新
  • {0,2}{2,0} {2,1}{2,3}有2不用算
  • {0,3}: A [ 0 ] [ 3 ] < A [ 0 ] [ 2 ] + A [ 2 ] [ 3 ] 7 < 9 + 2 A[0][3]<A[0][2]+A[2][3] \rightarrow 7<9+2 不更新
  • {1,0}: A [ 1 ] [ 0 ] = A [ 1 ] [ 2 ] + A [ 2 ] [ 0 ] > 4 + 3 A[1][0]=A[1][2]+A[2][0] \rightarrow \infin >4+3 更新
  • {3,0} A [ 3 ] [ 0 ] > A [ 3 ] [ 2 ] + A [ 2 ] [ 0 ] 4 = 1 + 2 A[3][0]>A[3][2]+A[2][0] \rightarrow 4 =1+2 不更新
  • 两个矩阵都分别跟新为如下两个
    在这里插入图片描述
  • 后面也都是一样,上次更新后直接以上次更新的那个矩阵为基础进行计算。这是以2为中间点进行更新的结果
  • 在这里插入图片描述
  • 这是3为中间点进行更新的结果
    在这里插入图片描述
    弗洛伊德算法就是利用矩阵的不断更新进行运算
    当然FLoyd算法也有MATLAB程序
    以Dijkstra算法那个例题为例,进行计算
clear;clc;
n=6; a=zeros(n);
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25; a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25; a(5,6)=55;
a=a+a'; 
a(a==0)=inf; %把所有零元素替换成无穷
a([1:n+1:n^2])=0; %对角线元素替换成零,Matlab中数据是逐列存储的
path=zeros(n);
for k=1:n
   for i=1:n
      for j=1:n
         if a(i,j)>a(i,k)+a(k,j)
            a(i,j)=a(i,k)+a(k,j);
            path(i,j)=k;
         end 
      end
   end
end
a, path

a =

     0    35    45    35    25    10
    35     0    15    20    30    25
    45    15     0    10    20    35
    35    20    10     0    10    25
    25    30    20    10     0    35
    10    25    35    25    35     0


path =

     0     6     5     5     0     0
     6     0     0     0     4     0
     5     0     0     0     0     4
     5     0     0     0     0     0
     0     4     0     0     0     1
     0     0     4     0     1     0

可以看到输出a是一个对称矩阵,代表两个点之间的距离,path代表路径,如[1,2]的数值是6,也就是经过了6这个中间点。

是不是只有距离这种题才能用这个模型呢?
在这里插入图片描述

设备更新问题。某公司使用一台设备,在每年年初,公司就要决定是购买新的设备还是继续使用旧设备。如果购置新设备,就要支付一定的购置费,当然新设备的维修费用就低。如果继续使用旧设备,这样可以省去了购置费,但维修费用就高了。现在需要我们制定一个五年之内的更新设备的计划,使得五年内购置费和维修费总的支付费用最小。

这种设备每年年初的价格如下表
在这里插入图片描述
另外,还已知使用不同时间(年)的设备所需要的维修费如下图
在这里插入图片描述
用点vi 表示第 i 年年初购进一台新设备,i=1, 2, 3, 4, 5, 6.
用弧 (vi,vj) 表示在第 i 年年初购进的设备一直使用到第 j 年年初,其中i<j
化为最短路问题后,相应的图示如下:
在这里插入图片描述
相应地,把费用转化为图中弧的权数。

对于弧 (vi,vj) ,其权数为从第 i 年年初购进设备使用到第 j-1 年年底所花费的购置费及维修费的总和。如下:
在这里插入图片描述
下面把计算得到的权数赋到图上,得到赋权图,则求解五年
内购置费和维修费总费用最小的问题就转化为从赋权图中求解一
条从 v1 到v6 的最短路问题。
在这里插入图片描述
最短路径:
v 1 v 3 v 6 v1→v3→v6 即:第1年初购置的新设备使用到第3年初 (第2年底) ,第3年初再购置新设备使用到第6年初 (第5年底) 。
v 1 v 4 v 6 v1→v4→v6 即:第1年初购置的新设备使用到第4年初 (第3年底) ,第4年初再购置新设备使用到第6年初 (第5年底)
两个路径耗费的金钱是一样的
用MATLAB

clear;clc;
n=6; a=zeros(n);
a(1,2)=16;a(1,3)=22;a(1,4)=30;a(1,5)=41;a(1,6)=59;
a(2,3)=16;a(2,4)=22;a(2,5)=22;a(2,6)=41; 
a(3,4)=17;a(3,5)=23;a(3,6)=31;
a(4,5)=17;a(4,6)=23;
a(5,6)=18;
a=a+a'; 
a(a==0)=inf; %把所有零元素替换成无穷
a([1:n+1:n^2])=0; %对角线元素替换成零,Matlab中数据是逐列存储的
path=zeros(n);
for k=1:n
   for i=1:n
      for j=1:n
         if a(i,j)>a(i,k)+a(k,j)
            a(i,j)=a(i,k)+a(k,j);
            path(i,j)=k;
         end 
      end
   end
end
a, path

下一篇数学建模之图论——图与网络模型(二)(最小生成树问题、最大流问题) https://blog.csdn.net/weixin_45755332/article/details/106946149

猜你喜欢

转载自blog.csdn.net/weixin_45755332/article/details/106899147