最短路(基礎(chǔ)未優(yōu)化)

最短路(基礎(chǔ)未優(yōu)化)

寫(xiě)在前面

寫(xiě)最短路我猶豫了很久,因?yàn)樽疃搪匪w的內(nèi)容很多(四個(gè)基礎(chǔ)算法)喘蟆,而且在基礎(chǔ)算法上還有許多不同的優(yōu)化缓升,甚至存邊都有幾種方式,就顯得特別復(fù)雜

基本概念

最短路就是求在一個(gè)圖中一個(gè)點(diǎn)到指定點(diǎn)的最短路程(其實(shí)光看名字就猜的出來(lái))蕴轨。

幾個(gè)概念:


1.出發(fā)的點(diǎn)叫源點(diǎn)
2.一個(gè)點(diǎn)到另一個(gè)點(diǎn)的路程(也可以理解為連接這兩個(gè)點(diǎn)的線(xiàn)段的長(zhǎng)度)叫權(quán)
3.圖分兩種:有向圖和無(wú)向圖港谊。有向圖就像單行道,只能去不能回橙弱。而無(wú)向圖就像雙行道歧寺,可以去也可以回。

還有一些例如松弛操作這些的概念會(huì)在下面進(jìn)行解釋

基礎(chǔ)算法

存邊

對(duì)于一個(gè)圖棘脐,我們需要把邊存儲(chǔ)下來(lái)斜筐。而存儲(chǔ)有兩種方式糜值。

鄰接矩陣

用一個(gè)二維數(shù)組來(lái)存儲(chǔ)偎快。假如用數(shù)組k來(lái)存儲(chǔ)邊,則

k[i][j]

表示有一條從i到j(luò)的邊焚刚,權(quán)值為

k[i][j]
鄰接表

思路是用3個(gè)數(shù)組屈梁,(這里假設(shè)為a,b,c)(可能有點(diǎn)難理解)
當(dāng)

a[m]=I
b[m]=j
c[m]=n(其中m為常數(shù))

就是表示從i到j(luò)有一條邊嗤练,權(quán)值為n。
但是假如要排序的話(huà)在讶,開(kāi)三個(gè)數(shù)組很麻煩煞抬,所以我建議用結(jié)構(gòu)體。而結(jié)構(gòu)體的排序方法我在講最小生成樹(shù)之kruskarl的時(shí)候講過(guò)构哺,這里就不再贅述革答。

前向星

前向星比鄰接矩陣省空間。

鏈?zhǔn)角跋蛐?/h5>

這個(gè)是一種鏈?zhǔn)降拇孢叿椒ㄊ锴俊<偃缫?xì)講的話(huà)残拐,可能又要講一篇文章了,下文也不會(huì)使用這個(gè)旗扑。
感興趣的話(huà)可以去看這篇博客

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

無(wú)向邊

以上講的都是存有向邊的方式蹦骑。存無(wú)向邊其實(shí)區(qū)別不是很大慈省。舉個(gè)例子相信一下就懂了臀防。假如你要存一條從i到j(luò)的無(wú)向邊眠菇,你可以這么寫(xiě)

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

就是把終點(diǎn)和起點(diǎn)換一下位置,把終點(diǎn)當(dāng)起點(diǎn)袱衷,把起點(diǎn)當(dāng)終點(diǎn)捎废。

Floyd

這個(gè)算法有一大特點(diǎn),那就是寫(xiě)起來(lái)極其簡(jiǎn)單(核心代碼只有5行)致燥,但是運(yùn)行效率極低(o(n^3))登疗,就讓它顯得很毒瘤,而且數(shù)據(jù)基本都會(huì)卡這種算法嫌蚤。
假如用二維數(shù)組

k[i][j]

來(lái)存儲(chǔ)從i到j(luò)的最段路辐益。
初始化:先把k數(shù)組全部賦一個(gè)很大很大的值(方便后面比較)
floyd算法如下

for(int k=1;k<=n;k++)//k枚舉途經(jīng)的節(jié)點(diǎn)
        for(int i=1;i<=n;i++)//i枚舉起點(diǎn)
            for(int j=1;j<=n;j++)//j枚舉終點(diǎn)
                if(d[i][j]!=inf&&d[i][k]!=inf)//假如i到k沒(méi)有邊,那么假設(shè)不成立脱吱,同理智政,假如i到j(luò)沒(méi)有邊,這個(gè)假設(shè)也不成立
                    d[i][j]=min(d[i][k]+d[k][j],d[i][j]);//拿現(xiàn)有的從i到j(luò)的最段路和i途經(jīng)k再到j(luò)的總路程做比較箱蝠。(這就是為什么要把d[i][j]的初始值賦為一個(gè)很大的數(shù))

可以看一下上面的注釋续捂。。
floyd就是靠三重循環(huán)來(lái)枚舉起點(diǎn)宦搬、途經(jīng)的點(diǎn)和終點(diǎn)牙瓢。然后做松弛操作。(松弛操作就是比大小那一步间校,有點(diǎn)像三角形的三邊關(guān)系)拿現(xiàn)有的從i到j(luò)的最段路和i途經(jīng)k再到j(luò)的總路程做比較矾克。也算是一個(gè)dp。
這個(gè)算法沒(méi)啥優(yōu)化(也沒(méi)啥可優(yōu)化的)撇簿∧粼ǎ可以求單源最段路(有向圖中的最段路),也可以求無(wú)向圖的最段路四瘫。不能對(duì)付負(fù)權(quán)

這里順便引入兩個(gè)新概念:負(fù)權(quán)&環(huán)
負(fù)權(quán):一條權(quán)值為負(fù)的路(于現(xiàn)實(shí)生活中不存在)汉嗽。
環(huán):有些時(shí)候在有向圖中會(huì)同時(shí)有從i到j(luò)和從j到i的兩條路。他們就組成了一個(gè)環(huán)找蜜。
負(fù)權(quán)環(huán)就是一個(gè)很恐怖的東西了饼暑,你可以靠負(fù)權(quán)環(huán)在環(huán)里面不停的刷,這樣你的最短路洗做。弓叛。。就成了無(wú)限的更短路诚纸。撰筷。。

dijkstra狄杰斯特拉算法

這是一個(gè)很經(jīng)典的單源最短路的算法畦徘。
這個(gè)算法的描述我覺(jué)得在一本叫算法圖解的書(shū)中描述的比較詳細(xì)毕籽,在這里就附上書(shū)的照片抬闯,覺(jué)得講得很通俗易懂,應(yīng)該理解沒(méi)有什么問(wèn)題关筒。(多圖預(yù)警)


1.jpg

2.jpg

3.jpg

4.jpg

5.jpg

總之就是重復(fù)那四步溶握,就可以找出最優(yōu)解。
算法效率比f(wàn)loyd不知道高到哪里去了蒸播。睡榆。
不能對(duì)付負(fù)權(quán)

bellman-ford貝爾曼福德算法

這是一個(gè)可以對(duì)付負(fù)權(quán)的算法
算法:

給你一個(gè)由v個(gè)點(diǎn),e條邊的圖袍榆,和原點(diǎn)s

數(shù)組Distant[i]記錄從源點(diǎn)s到頂點(diǎn)i的路徑長(zhǎng)度胀屿,初始化

數(shù)組Distant[n]為, Distant[s]為0;

以下操作循環(huán)執(zhí)行至多n-1次包雀,n為頂點(diǎn)數(shù):

對(duì)于每一條邊e(u, v)碉纳,如果Distant[u] + w(u, v) < Distant[v],則另Distant[v] = Distant[u]+w(u, v)馏艾。w(u, v)為邊e(u,v)的權(quán)值劳曹;

若上述操作沒(méi)有對(duì)Distant進(jìn)行更新,說(shuō)明最短路徑已經(jīng)查找完畢琅摩,或者部分點(diǎn)不可達(dá)铁孵,跳出循環(huán)。否則執(zhí)行下次循環(huán)房资;

為了檢測(cè)圖中是否存在負(fù)環(huán)路蜕劝,即權(quán)值之和小于0的環(huán)路。對(duì)于每一條邊e(u, v)轰异,如果存在Distant[u] + w(u, v) < Distant[v]的邊岖沛,則圖中存在負(fù)環(huán)路,即是說(shuō)改圖無(wú)法求出單源最短路徑搭独。否則數(shù)組Distant[n]中記錄的就是源點(diǎn)s到各頂點(diǎn)的最短路徑長(zhǎng)度婴削。

可知,Bellman-Ford算法尋找單源最短路徑的時(shí)間復(fù)雜度為O(V*E).

Bellman-Ford算法可以大致分為三個(gè)部分

第一牙肝,初始化所有點(diǎn)唉俗。每一個(gè)點(diǎn)保存一個(gè)值,表示從原點(diǎn)到達(dá)這個(gè)點(diǎn)的距離配椭,將原點(diǎn)的值設(shè)為0虫溜,其它的點(diǎn)的值設(shè)為無(wú)窮大(表示不可達(dá))。

第二股缸,進(jìn)行循環(huán)衡楞,循環(huán)下標(biāo)為從1到n-1(n等于圖中點(diǎn)的個(gè)數(shù))。在循環(huán)內(nèi)部敦姻,遍歷所有的邊瘾境,進(jìn)行松弛計(jì)算坎背。

第三,遍歷途中所有的邊(edge(u寄雀,v)),判斷是否存在這樣情況:
d(v) > d (u) + w(u,v)

則返回false陨献,表示途中存在從源點(diǎn)可達(dá)的權(quán)為負(fù)的回路盒犹。

松弛操作之前講過(guò),再看一遍復(fù)習(xí)一下


a.png

松弛計(jì)算之前眨业,點(diǎn)B的值是8急膀,但是點(diǎn)A的值加上邊上的權(quán)重2,得到5龄捡,比點(diǎn)B的值(8)小卓嫂,所以,點(diǎn)B的值減小為5聘殖。這個(gè)過(guò)程的意義是晨雳,找到了一條通向B點(diǎn)更短的路線(xiàn),且該路線(xiàn)是先經(jīng)過(guò)點(diǎn)A奸腺,然后通過(guò)權(quán)重為2的邊餐禁,到達(dá)點(diǎn)B。
當(dāng)然突照,如果出現(xiàn)以下情況


b.png

則不會(huì)修改點(diǎn)B的值帮非,因?yàn)?+4>6。

spfa留著下次再講(和優(yōu)化一起讹蘑,因?yàn)樗容^難末盔。。)座慰。(留坑待補(bǔ))
會(huì)了Bellman-Ford算法和狄杰斯特拉算法就已經(jīng)可以做一些最段路的題了陨舱,可以練習(xí)一下。

重點(diǎn)理解:松弛操作(這玩意真的很重要版仔,基本上最段路的精髓就是它了)

tks隅忿!
(參考文獻(xiàn):https://www.cnblogs.com/tanky_woo/archive/2011/01/17/1937728.html , 算法圖解)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邦尊,一起剝皮案震驚了整個(gè)濱河市背桐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝉揍,老刑警劉巖链峭,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異又沾,居然都是意外死亡弊仪,警方通過(guò)查閱死者的電腦和手機(jī)熙卡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)励饵,“玉大人驳癌,你說(shuō)我怎么就攤上這事∫厶” “怎么了颓鲜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)典予。 經(jīng)常有香客問(wèn)我甜滨,道長(zhǎng),這世上最難降的妖魔是什么瘤袖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任衣摩,我火速辦了婚禮,結(jié)果婚禮上捂敌,老公的妹妹穿的比我還像新娘艾扮。我一直安慰自己,他們只是感情好占婉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布栏渺。 她就那樣靜靜地躺著,像睡著了一般锐涯。 火紅的嫁衣襯著肌膚如雪磕诊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天纹腌,我揣著相機(jī)與錄音霎终,去河邊找鬼。 笑死升薯,一個(gè)胖子當(dāng)著我的面吹牛莱褒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涎劈,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼广凸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蛛枚?” 一聲冷哼從身側(cè)響起谅海,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蹦浦,沒(méi)想到半個(gè)月后扭吁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年侥袜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蝌诡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡枫吧,死狀恐怖浦旱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情九杂,我是刑警寧澤颁湖,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站尼酿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏植影。R本人自食惡果不足惜裳擎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望思币。 院中可真熱鬧鹿响,春花似錦、人聲如沸谷饿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)博投。三九已至绸贡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毅哗,已是汗流浹背听怕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虑绵,地道東北人尿瞭。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像翅睛,于是被迫代替她去往敵國(guó)和親声搁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 參見(jiàn)貪心算法——最短路徑Dijkstra算法參見(jiàn)動(dòng)態(tài)規(guī)劃 目錄 0.最短路徑問(wèn)題0.1 最短路徑問(wèn)題描述?0.1....
    王偵閱讀 4,816評(píng)論 1 9
  • 簡(jiǎn)介 搜索迷宮(BFS+隊(duì)列) 最短路Dijkstra+鄰接矩陣Dijkstra+鏈?zhǔn)角跋蛐?優(yōu)先隊(duì)列Bellma...
    染微言閱讀 397評(píng)論 0 1
  • 本文將介紹三種常見(jiàn)的最短路算法:Dijkstra捕发,F(xiàn)loyd疏旨,SPFA Dijkstra Dijkstra是有向圖...
    maxkibble閱讀 1,488評(píng)論 0 0
  • “沒(méi)能力,自己去學(xué)習(xí) 沒(méi)人脈骤铃,自己去勾搭 沒(méi)渠道拉岁,自己去建立 千萬(wàn)不要把自己的前途,建立在任何人身上惰爬『芭“ 以上幾句...
    小小故事大智慧閱讀 466評(píng)論 0 0
  • 如果你丟了一件心愛(ài)的東西,可能你會(huì)念念不忘撕瞧,但是當(dāng)你遇到更好的陵叽,你一定會(huì)坦然放手吧。
    在有你的時(shí)光里閱讀 104評(píng)論 0 1