最近看离散数学图的部分根据自己的理解,整理了一下笔记

图的基本概念

这里所说的图是一种抽象的数学概念,并不是图片图像什么的,类似质点的概念,只不过可以用图行化表示出来。比如有四个城市{A,B,C,D},我们想要描述他们之间的公路连通关系,我们画四个点,称为顶点(图中的顶点数>0),表示这四个城市

Fig1

图的基本概念和Dijkstra算法

这也算一个图了,但是顶点之间没有关系,这个关系称为,这样的图被称为零图,对于没有边的任何一个顶点都是孤立顶点,上面就有A,B,C,D四个孤立顶点。

然后在相互之间连线表示互相连通,有以下的图,其中(A,B)互相连通,(A,D)不连通,其他同理

Fig2
图的基本概念和Dijkstra算法

上面说的是简单图,简单图指的是没有环和平行边的图,如果有平行边(即两个顶点之间有多条边,则他们是平行的),则这个图是多重图

Fig3

图的基本概念和Dijkstra算法

如果有环会出现以下情况(即一个顶点到自身有一条边,这条边就是环),下面的顶点B就有一个环,但这个属于多重图和简单图

FIg4

图的基本概念和Dijkstra算法

实际研究学习的时候,还接触到HyperGraph,读者可以自行到维基了解。

图的同构

由于图是一种抽象关系的描述工具,实际上,我们如果把简单图中的A,B,C,D,换成E,F,G,H(如下图所示),他们表示的图也是相同的

Fig5

图的基本概念和Dijkstra算法
而在实际作图的过程中,每个城市可能会根据数量关系(之后介绍,即关于集合的部分)有不同的方式去画同一幅图,我们并不关心怎么画这图,而关注的是他们之间的关系,这样的图也是相同的。我们称这样两个相同的图是同构的。如下图所示,

Fig6

图的基本概念和Dijkstra算法
Fig7
图的基本概念和Dijkstra算法

子图

如果我们在某些场景下只需要表示,一个图部分顶点和部分边,就产生了子图的概念,最开始的图称为母图(也有称为始图的),而子图是保留母图中的部分顶点和部分边的结果(不能产生新的边),即顶点集合是母图的非空子集,边集合也是母图的子集。依旧拿上面的简单图A,B,C,D来说,以下都是它的子图,(当然还有很多)

去掉顶点的子图(顺带去掉了相应边)

Fig8

图的基本概念和Dijkstra算法
只去掉边的子图

Fig9

图的基本概念和Dijkstra算法

说到子图,不得不说一下子图相关概念,其中就有支撑子图,支撑子图指的是母图中所有的顶点都在子图中,但是母图中边可以不用都在子图里面,毕竟还是子集嘛,比如只去掉边的子图Fig9也是支撑子图,显然下面的图也是,(当然还是不止这些)

Fig10

图的基本概念和Dijkstra算法

其次还要说一下,诱导子图,诱导子图其实还是比较简单的,就是有一个子图,如果它包含了母图中的某些点,那么它必须包含这些点在母图中对应的边(如果之前顶点之间没有边就不管),所以上面只去掉边的子图Fig9的例子就不是诱导子图了,去掉顶点的子图Fig8的例子恰好是一个诱导子图,下面再举一个例子,没有顶点C的诱导子图
Fig11
图的基本概念和Dijkstra算法

补图

如果母图去掉子图包含所有的边剩下的图(节点数与母图相同),称为相对补图

子图

Fig12

图的基本概念和Dijkstra算法
该子图关于母图Fig2的相对补图

Fig13

图的基本概念和Dijkstra算法

下面介绍一下完全图,完全图,简而言之,就是给定一个顶点集合,任意两个顶点之间都有边,比如对于ABCD来,他的完全图是这样的,对于更多顶点就会更加麻烦了。

Fig14

图的基本概念和Dijkstra算法

而实际上任意一个图都有补图,这个补图,是相对于它的完全图(严谨的说应该是它点集的完全图)的相对补图,

对于最开始的简单图ABCD来说它的补图其实就是这样的

Fig15

图的基本概念和Dijkstra算法

当然对于它的子图Fig12的补图,注意这里不是关于母图的相对补图了,是子图本身的补图,别弄混淆了,就

Fig16

图的基本概念和Dijkstra算法

权图

当我们要表示,城市间的距离的时候,我们可以再对应的边上加上一个实数,称为权值,用ω\omega表示。比如我们再简单图ABCD加上路径长度时,就可以表示成这样,显然 ω(AB)=3\omega(AB)=3ω(AC)=4\omega(AC)=4

Fig17

图的基本概念和Dijkstra算法

但是如果两个顶点之间没有边的存在,我们就认为他们之间的权值(距离)为无穷大,比如ω(AD)=\omega(AD)=\infty,有时候,我们可能用到顶点到自己的权值,所以我们规定ω(AA)=0\omega(AA)=0

实际上是两个顶点之间的路径,用顶点序列来表示(实际上我觉得用边序列来表示也可以),比如Fig17中的AD之间的路就表示为(A,C,D),实际上我们并没有规定每个顶点只走一次,所以(A,B,A,C,D)也算AD之间的路。下图是路(A,C,D)

FIg18

图的基本概念和Dijkstra算法

要是只走一次呢,就称为简单路(但是端点可以相同,所以(A,B,A)也算简单路),所以(A,C,D)是简单路,(A,B,A,C,D)不是简单路.

注意路中的顶点序列是相邻的,相邻即,在序列中,连续的两个顶点需作为同一条边的端点,比如顶点A和C相邻,A和D不相邻

最短路径

两个端点之间可能有多条路,比如下图AC之间有(A,C),(A,B,C),(A,D,C)等路径,其中路径上的边权值和最小的称为最短路径,经计算,AC之间最短路径是也刚好是(A,B,C)(有时候可能绕个弯却会更短),且路径长度为7,我们称这个AC最短路径长度为AC之间的距离,记为 d(A,C)=7d(A,C)=7

Fig19
图的基本概念和Dijkstra算法

Dijkstra算法

我们再上面使用的计算最短路径的方法是枚举法,就是简单地举出所有路径,并计算长度,当图的规模变大了,比如包含几百个顶点,几万条边,这个方法就不靠谱了。下面介绍Dijkstra算法。

首先我们在最短路径那里定义了点之间的距离,下面引入点与点集合之间的距离,如下图所示,当整个图的点集GG{A,B,C,D}\{A,B,C,D\}时,比如有一个点集合S={B,D}S=\{B,D\},一个点为AA,我们定义AASS的距离,为AASS中的每一点vv的距离最小值,记作d(A,S)=minvS{d(A,v)}d(A,S)=\min\limits_{v\in S}\{d(A,v)\},显然d(A,S)=min{d(A,B),d(A,D)}d(A,S)=\min\{d(A,B),d(A,D)\}

Fig20
图的基本概念和Dijkstra算法

我们可以在S=GSS'=G-S中找到一点uu(可以是AA本身), 使得d(A,S)=minvS{d(A,v)}=minvSuS{d(A,u)+ω(u,v)}d(A,S)=\min\limits_{v\in S}\{d(A,v)\}=\min\limits_{v\in S\\u\in S'}\{d(A,u)+\omega(u,v)\}

所以可以有如下组合

u=Au=A时,d(A,A)=0d(A,A)=0,ω(A,B)=4\omega(A,B)=4,ω(A,D)=7\omega(A,D)=7,所以

minuS{d(A,u)+ω(u,v)}=min{d(A,A)+ω(A,B),d(A,A)+ω(A,D)}=min{0+4,0+7}=4\min\limits_{u\in S'}\{d(A,u)+\omega(u,v)\}=\min\{d(A,A)+\omega(A,B),d(A,A)+\omega(A,D)\}=\min\{0+4,0+7\}=4

u=Cu=C时,d(A,C)=8d(A,C)=8,ω(C,B)=3\omega(C,B)=3,ω(C,D)=\omega(C,D)=\infty(这里不是距离,而是边的权值),有

minuS{d(A,u)+ω(u,v)}=min{d(A,C)+ω(C,B),d(A,C)+ω(C,D)}=min{8+3,8+}=11\min\limits_{u\in S'}\{d(A,u)+\omega(u,v)\}=\min\{d(A,C)+\omega(C,B),d(A,C)+\omega(C,D)\}=\min\{8+3,8+\infty\}=11

综上所述

d(A,S)=minvSuS{d(A,u)+ω(u,v)}=4d(A,S)=\min\limits_{v\in S\\u\in S'}\{d(A,u)+\omega(u,v)\}=4

其实从这里就可以看到Dijkstra的影子了,下面给出简单版本算法

目标:求给定点u0u_0到图中各点的最短距离(亦称单源最短路径)

1.初始化S={u0}S'=\{u_0\},给定点集S=PSS=P-S',对于SS中的每一点vv,令d(u0,v)=d(u0,u0)+ω(u0,v)d(u_0,v)=d(u_0,u_0)+\omega(u_0,v)(显然这里的u=u0u=u_0)

2.找出u0u_0SS的最短距离,并确定该点uiu_i,即在S中找出一点uiu_i使得d(u0,ui)d(u_0,u_i)最小,用公式表示为

d(u0,ui)=minvS{d(u0,v)}d(u_0,u_i)=\min\limits_{v\in S}\{d(u_0,v)\}

3.若SPS\neq P,从给定点集S中删除uiu_i,并将其加入到SS'中,用公式表示为S=S{ui},S=S{ui}S=S-\{u_i\},S'=S'\cup\{u_i\}

​ 否则当S=PS=P时,则终止

4.对于新的S中的每一个点vv,重新计算d(u0,v)=minuS{d(u0,u)+ω(u,v)}d(u_0,v)=\min\limits_{u\in S'}\{d(u_0,u)+\omega(u,v)\}

其实上面基本能用了,但是还有一些地方可以优化的

其一,对于二维数组d(u,v)d(u,v)实际上我们只使用了d(u0,v)d(u_0,v),所以可以将它优化成一维数组d(v)d(v)

再者,第4步,重新计算d(u0,v)=minuS{d(u0,u)+ω(u,v)}d(u_0,v)=\min\limits_{u\in S'}\{d(u_0,u)+\omega(u,v)\}的时候有很多重复计算,让我们看看那里出来的重复计算?

S={u0,u1,...ui}S'=\{u_0,u_1,...u_i\}时,

d(u0,v)=minuS{d(u0,u)+ω(u,v)}=min{d(u0,u0)+ω(u0,v),d(u0,u1)+ω(u1,v),...,d(u0,ui)+ω(ui,v)}d(u_0,v)\\=\min\limits_{u\in S'}\{d(u_0,u)+\omega(u,v)\}\\=\min\{d(u_0,u_0)+\omega(u_0,v),d(u_0,u_1)+\omega(u_1,v),...,d(u_0,u_i)+\omega(u_i,v)\}

S={u0,u1,...ui,ui+1}S'=\{u_0,u_1,...u_i,u_{i+1}\}时,

d(u0,v)=minuS{d(u0,u)+ω(u,v)}=min{d(u0,u0)+ω(u0,v),d(u0,u1)++ω(u1,v)...,d(u0,ui)+ω(ui,v),d(u0,ui+1)+ω(ui+1,v)}d(u_0,v)\\=\min\limits_{u\in S'}\{d(u_0,u)+\omega(u,v)\}\\=\min\{d(u_0,u_0)+\omega(u_0,v),d(u_0,u_1)++\omega(u_1,v)...,d(u_0,u_i)+\omega(u_i,v),d(u_0,u_{i+1})+\omega(u_{i+1},v)\}

我们可以发现,在计算S’={u0,u1,....ui+1}\{u_0,u_1,....u_{i+1}\}最小值的时候,又计算了一遍在{u0,u1,....ui}\{u_0,u_1,....u_i\}中的最小值,其实已经保存了{u0,u1,....ui}\{u_0,u_1,....u_i\}的最小值,就直接和uiu_i对应的值比较就行了。

就优化成这样

d(u0,v)=minuS{d(u0,u)+ω(u,v)}=min{d(u0,v),d(u0,ui+1)+ω(ui+1,v)}d(u_0,v)\\=\min\limits_{u\in S'}\{d(u_0,u)+\omega(u,v)\}\\=\min\{d(u_0,v),d(u_0,u_{i+1})+\omega(u_{i+1},v)\}

结合前面两个优化,最后的Dijkstra算法如下

1.初始化S={u0}S'=\{u_0\},给定点集S=PSS=P-S',对于SS中的每一点vv,令d(v)=d(u0)+ω(u0,v)d(v)=d(u_0)+\omega(u_0,v)(显然这里的u=u0u=u_0)

2.找出u0u_0SS的最短距离,并确定该点uiu_i,即在S中找出一点uiu_i使得d(ui)d(u_i)最小,用公式表示为

d(ui)=minvS{d(v)}d(u_i)=\min\limits_{v\in S}\{d(v)\}

3.若SPS\neq P,从给定点集S中删除uiu_i,并将其加入到SS'中,用公式表示为S=S{ui},S=S{ui}S=S-\{u_i\},S'=S'\cup\{u_i\}

​ 否则当S=PS=P时,则终止

4.对于新的S中的每一个点vv,重新计算d(v)=minuS{d(u)+ω(u,v)}d(v)=\min\limits_{u\in S'}\{d(u)+\omega(u,v)\}

当然其中d(u0)=0d(u_0)=0,是可以省略的

关于证明:

证明这条路径时最小的,其实考虑三个方面(路径第一步进入S,路径最后一步进入S,路径中间某步进入S),简单放缩一下,具体参考课本

相关文章:

  • 2021-06-06
  • 2021-07-23
  • 2022-03-01
  • 2021-11-09
  • 2021-12-18
猜你喜欢
  • 2021-11-10
  • 2022-01-04
  • 2021-05-20
相关资源
相似解决方案