无向图(简称图):没有方向,由点和边构成的图,记做G =(V , E),点是V,边是E。
注:图论的图与几何图、工程图不一样。
因为一般情况下的图中点的相对位置及点间连线长短,对于反映对象之间的关系并不是重要的。
联结 v i 1 v_i{_1} vi1 和 v i k v_{ik} vik 的链:在无向图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} vi1,ei1,vi2,ei2,...vik−1,eik−1,cik)其中 v i k v_{ik} vik属于V(G), e i j e_{ij} eij属于E(G)
联结 v_{i1} 和 v_{ik} 的圈:在上述的链中,若 v_{i1} = v_{ik},也就是首尾相连。
连通图:对于一个无向图,若任何两个不同的点之间,至少存在一条链。
简单图:一个图如果它既没有环也没有平行边(两条边连接同一对顶点),称为简单图(simple graph)。
完全图:其中每对不同的顶点之间都恰连有一条边相连
赋权图:对无向图的每一条边( v i , v j v_i,v_j vi,vj) ,都有一个数(称为权重) w i j w_{ij} wij对应。
二分图又称作二部图,是图论中的一种特殊模型。 设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} vi1 和 v i k v_{ik} vik 的路:在无向图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} vi1,ei1,vi2,ei2,...vik−1,eik−1,cik)其中 v i k v_{ik} vik属于V(D), e i j e_{ij} eij属于V(D)
*联结 v_{i1} 和 v_{ik} 的回路:在上述的链中,若 v_{i1} = v_{ik},也就是首尾相连。
赋权图:对无向图的每一条弧( v i , v j v_i,v_j vi,vj) ,都有一个数(称为权重) c i j c_{ij} cij对应。
网络:在赋权的有向图D中指定一点为发点(记为 v s v_s vs ),指定另一点为收点(记为 v t v_t vt),其余的点为中间点,并把 D 中的每一条弧的赋权数 c i j c_ij cij 称为弧 ( v i , v j ) (v_i,v_j) (vi,vj) 的容量 ,这样的赋权有向图 D 就称为网络。
描述图与网络的3种常用表示方法:邻接矩阵表示法、关联矩阵表示法、弧表表示法
邻接矩阵表示法是将图以邻接矩阵(adjacency matrix)的形式存储在计算机中。图 G=(V,A) 的邻接矩阵是如下定义的:C是一个 n ∗ n n*n n∗n的0-1矩阵,即
也就是说,如果两节点之间有一条弧,则邻接矩阵中对应的元素为1;否则为0。
例一:对于下图,可以用邻接矩阵表示为
解释:现在有五个图,邻接矩阵a就是 5 ∗ 5 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=(bik)n∗m∈(−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 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,则弧表表示如下:
最短路问题:对一个赋权有向图中指定的两个点 v s v_s vs和 v t v_t vt找到条从 v s v_s vs到 v t v_t vt的路,使得这条路上所有弧的权数总和最小,这条路被称为从 v s v_s vs 到 v t v_t vt, 的最短路,这条路_上所有弧的权数的总和被称为从 v s v_s vs到 v t v_t vt 的距离。
如上图,带权值的最短路径长度就是黄线标出来的 为7
求解最短路的迪克斯特拉Dijkstra算法(双标号法)
双标号即:对图中的点 v j v_j vj 赋予两个标号 ( l j , k j ) (l_j,k_j) (lj,kj) ,其中 l_j 表示从起点 v s v_s vs 到 v j v_j vj 的最短路的长度, k j k_j kj 表示在 v s v_s vs 至 v j v_j vj 的最短路上前面一个邻点的下标,从而找到所求的最短路及其距离。
下 面 给 出 D i j k s t r a 算 法 的 基 本 步 骤 : {\mathbb{\color{Red}下面给出Dijkstra算法的基本步骤:}} 下面给出Dijkstra算法的基本步骤:
标号(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
其他的以此类推
主要用来计算每对顶点之间的最短路径。
Dijkstra算法用来计算一对顶点之间的最短路径。
Floyd算法的基本思想是:递推产生一个矩阵序列 A 0 , A 1 . . . A k . . . A n A_0,A_1...A_k...A_n A0,A1...Ak...An ,其中 A k ( i , j ) A_k(i,j) Ak(i,j) 表示从顶点 v i v_i vi到顶点 v j v_j vj 的路径上所经过的顶点序号不大于k的最
短路径度。迭代公式为:
k是迭代次数, i , j , k = 1 , 2 , 3 , . . . n 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}
再以顶点2为中间点进行检测
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
相应地,把费用转化为图中弧的权数。
对于弧 (vi,vj) ,其权数为从第 i 年年初购进设备使用到第 j-1 年年底所花费的购置费及维修费的总和。如下:
下面把计算得到的权数赋到图上,得到赋权图,则求解五年
内购置费和维修费总费用最小的问题就转化为从赋权图中求解一
条从 v1 到v6 的最短路问题。
最短路径:
v 1 → v 3 → v 6 v1→v3→v6 v1→v3→v6 即:第1年初购置的新设备使用到第3年初 (第2年底) ,第3年初再购置新设备使用到第6年初 (第5年底) 。
v 1 → v 4 → v 6 v1→v4→v6 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