最短路(基础未优化)

最短路(基础未优化)

写在前面

写最短路我犹豫了很久,因为最短路它涵盖的内容很多(四个基础算法),而且在基础算法上还有许多不同的优化,甚至存边都有几种方式,就显得特别复杂

基本概念

最短路就是求在一个图中一个点到指定点的最短路程(其实光看名字就猜的出来)。

几个概念:


1.出发的点叫源点
2.一个点到另一个点的路程(也可以理解为连接这两个点的线段的长度)叫权
3.图分两种:有向图和无向图。有向图就像单行道,只能去不能回。而无向图就像双行道,可以去也可以回。

还有一些例如松弛操作这些的概念会在下面进行解释

基础算法

存边

对于一个图,我们需要把边存储下来。而存储有两种方式。

邻接矩阵

用一个二维数组来存储。假如用数组k来存储边,则

k[i][j]

表示有一条从i到j的边,权值为

k[i][j]
邻接表

思路是用3个数组,(这里假设为a,b,c)(可能有点难理解)

a[m]=I
b[m]=j
c[m]=n(其中m为常数)

就是表示从i到j有一条边,权值为n。
但是假如要排序的话,开三个数组很麻烦,所以我建议用结构体。而结构体的排序方法我在讲最小生成树之kruskarl的时候讲过,这里就不再赘述。

前向星

前向星比邻接矩阵省空间。

链式前向星

这个是一种链式的存边方法。假如要细讲的话,可能又要讲一篇文章了,下文也不会使用这个。
感兴趣的话可以去看这篇博客

https://blog.csdn.net/acdreamers/article/details/16902023/

无向边

以上讲的都是存有向边的方式。存无向边其实区别不是很大。举个例子相信一下就懂了。假如你要存一条从i到j的无向边,你可以这么写

k[i][j]=n;
k[j][i]=n;

就是把终点和起点换一下位置,把终点当起点,把起点当终点。

Floyd

这个算法有一大特点,那就是写起来极其简单(核心代码只有5行),但是运行效率极低(o(n^3)),就让它显得很毒瘤,而且数据基本都会卡这种算法。
假如用二维数组

k[i][j]

来存储从i到j的最段路。
初始化:先把k数组全部赋一个很大很大的值(方便后面比较)
floyd算法如下

for(int k=1;k<=n;k++)//k枚举途经的节点
        for(int i=1;i<=n;i++)//i枚举起点
            for(int j=1;j<=n;j++)//j枚举终点
                if(d[i][j]!=inf&&d[i][k]!=inf)//假如i到k没有边,那么假设不成立,同理,假如i到j没有边,这个假设也不成立
                    d[i][j]=min(d[i][k]+d[k][j],d[i][j]);//拿现有的从i到j的最段路和i途经k再到j的总路程做比较。(这就是为什么要把d[i][j]的初始值赋为一个很大的数)

可以看一下上面的注释。。
floyd就是靠三重循环来枚举起点、途经的点和终点。然后做松弛操作。(松弛操作就是比大小那一步,有点像三角形的三边关系)拿现有的从i到j的最段路和i途经k再到j的总路程做比较。也算是一个dp。
这个算法没啥优化(也没啥可优化的)。可以求单源最段路(有向图中的最段路),也可以求无向图的最段路。不能对付负权

这里顺便引入两个新概念:负权&环
负权:一条权值为负的路(于现实生活中不存在)。
环:有些时候在有向图中会同时有从i到j和从j到i的两条路。他们就组成了一个环。
负权环就是一个很恐怖的东西了,你可以靠负权环在环里面不停的刷,这样你的最短路。。。就成了无限的更短路。。。

dijkstra狄杰斯特拉算法

这是一个很经典的单源最短路的算法。
这个算法的描述我觉得在一本叫算法图解的书中描述的比较详细,在这里就附上书的照片,觉得讲得很通俗易懂,应该理解没有什么问题。(多图预警)


1.jpg

2.jpg

3.jpg

4.jpg

5.jpg

总之就是重复那四步,就可以找出最优解。
算法效率比floyd不知道高到哪里去了。。
不能对付负权

bellman-ford贝尔曼福德算法

这是一个可以对付负权的算法
算法:

给你一个由v个点,e条边的图,和原点s

数组Distant[i]记录从源点s到顶点i的路径长度,初始化

数组Distant[n]为, Distant[s]为0;

以下操作循环执行至多n-1次,n为顶点数:

对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;

若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;

为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

可知,Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).

Bellman-Ford算法可以大致分为三个部分

第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。

第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。

第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:
d(v) > d (u) + w(u,v)

则返回false,表示途中存在从源点可达的权为负的回路。

松弛操作之前讲过,再看一遍复习一下


a.png

松弛计算之前,点B的值是8,但是点A的值加上边上的权重2,得到5,比点B的值(8)小,所以,点B的值减小为5。这个过程的意义是,找到了一条通向B点更短的路线,且该路线是先经过点A,然后通过权重为2的边,到达点B。
当然,如果出现以下情况


b.png

则不会修改点B的值,因为3+4>6。

spfa留着下次再讲(和优化一起,因为它比较难。。)。(留坑待补)
会了Bellman-Ford算法和狄杰斯特拉算法就已经可以做一些最段路的题了,可以练习一下。

重点理解:松弛操作(这玩意真的很重要,基本上最段路的精髓就是它了)

tks!
(参考文献:https://www.cnblogs.com/tanky_woo/archive/2011/01/17/1937728.html , 算法图解)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容