日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

单源最短路——dijkstra算法

發(fā)布時(shí)間:2025/4/9 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单源最短路——dijkstra算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Dijkstra算法

1.定義概覽

Dijkstra(迪杰斯特拉)算法是典型的單源最短路徑算法,用于計(jì)算一個(gè)節(jié)點(diǎn)到其他所有節(jié)點(diǎn)的最短路徑。主要特點(diǎn)是以起始點(diǎn)為中心向外層層擴(kuò)展,直到擴(kuò)展到終點(diǎn)為止。

問題描述:在無向圖 G=(V,E) 中,假設(shè)每條邊 E[i] 的長(zhǎng)度為 w[i],找到由頂點(diǎn) V0 到其余各點(diǎn)的最短路徑。(單源最短路徑)

?

2.算法描述

1)算法思想:設(shè)G=(V,E)是一個(gè)帶權(quán)有向圖,把圖中頂點(diǎn)集合V分成兩組,第一組為已求出最短路徑的頂點(diǎn)集合(用S表示,初始時(shí)S中只有一個(gè)源點(diǎn),以后每求得一條最短路徑 , 就將加入到集合S中,直到全部頂點(diǎn)都加入到S中,算法就結(jié)束了),第二組為其余未確定最短路徑的頂點(diǎn)集合(用U表示),按最短路徑長(zhǎng)度的遞增次序依次把第二組的頂點(diǎn)加入S中。在加入的過程中,總保持從源點(diǎn)v到S中各頂點(diǎn)的最短路徑長(zhǎng)度不大于從源點(diǎn)v到U中任何頂點(diǎn)的最短路徑長(zhǎng)度。此外,每個(gè)頂點(diǎn)對(duì)應(yīng)一個(gè)距離,S中的頂點(diǎn)的距離就是從v到此頂點(diǎn)的最短路徑長(zhǎng)度,U中的頂點(diǎn)的距離,是從v到此頂點(diǎn)只包括S中的頂點(diǎn)為中間頂點(diǎn)的當(dāng)前最短路徑長(zhǎng)度。

?

2)算法步驟:

a.初始時(shí),S只包含源點(diǎn),即S={v},v的距離為0。U包含除v外的其他頂點(diǎn),即:U={其余頂點(diǎn)},若v與U中頂點(diǎn)u有邊,則<u,v>正常有權(quán)值,若u不是v的出邊鄰接點(diǎn),則<u,v>權(quán)值為∞。

b.從U中選取一個(gè)距離v最小的頂點(diǎn)k,把k,加入S中(該選定的距離就是v到k的最短路徑長(zhǎng)度)。

c.以k為新考慮的中間點(diǎn),修改U中各頂點(diǎn)的距離;若從源點(diǎn)v到頂點(diǎn)u的距離(經(jīng)過頂點(diǎn)k)比原來距離(不經(jīng)過頂點(diǎn)k)短,則修改頂點(diǎn)u的距離值,修改后的距離值的頂點(diǎn)k的距離加上邊上的權(quán)。

d.重復(fù)步驟b和c直到所有頂點(diǎn)都包含在S中。

?

執(zhí)行動(dòng)畫過程如下圖

?

?

動(dòng)圖太快可以看下面的例子:


??

?

?

?

?

?

重點(diǎn)需要理解這句拗口的”按最短路徑長(zhǎng)度的遞增次序依次把第二組的頂點(diǎn)加入S中。在加入的過程中,總保持從源點(diǎn)vS中各頂點(diǎn)的最短路徑長(zhǎng)度不大于從源點(diǎn)vU中任何頂點(diǎn)的最短路徑長(zhǎng)度

?

實(shí)際上,Dijkstra?算法是一個(gè)排序過程,就上面的例子來說,是根據(jù)A到圖中其余點(diǎn)的最短路徑長(zhǎng)度進(jìn)行排序,路徑越短越先被找到,路徑越長(zhǎng)越靠后才能被找到,要找A到F的最短路徑,我們依次找到了?
A –> C?的最短路徑?3?
A –> C –> B?的最短路徑?5?
A –> C –> D?的最短路徑?6?
A –> C –> E?的最短路徑?7?
A –> C –> D –> F?的最短路徑?9?

?

為什么Dijkstra?算法不適用于帶負(fù)權(quán)的圖??
就上個(gè)例子來說,當(dāng)把一個(gè)點(diǎn)選入集合S時(shí),就意味著已經(jīng)找到了從A到這個(gè)點(diǎn)的最短路徑,比如第二步,把C點(diǎn)選入集合S,這時(shí)已經(jīng)找到A到C的最短路徑了,但是如果圖中存在負(fù)權(quán)邊,就不能再這樣說了。舉個(gè)例子,假設(shè)有一個(gè)點(diǎn)Z,Z只與A和C有連接,從A到Z的權(quán)為50,從Z到C的權(quán)為-49,現(xiàn)在A到C的最短路徑顯然是A –> Z –> C

再舉個(gè)例子:

?

在這個(gè)圖中,求從A到C的最短路,如果用Dijkstra根據(jù)貪心的思想,選擇與A最接近的點(diǎn)C,長(zhǎng)度為7,以后不再變化。但是很明顯此圖最短路為5。歸結(jié)原因是Dijkstra采用貪心思想,不從整體考慮結(jié)果,只從當(dāng)前情況考慮選擇最優(yōu)。

4.代碼模板

1 #include<stdio.h> 2 #include<string.h> 3 #define inf 0x3f3f3f3f 4 int map[110][110],dis[110],visit[110]; 5 /* 6 關(guān)于三個(gè)數(shù)組:map數(shù)組存的為點(diǎn)邊的信息,比如map[1][2]=3,表示1號(hào)點(diǎn)和2號(hào)點(diǎn)的距離為3 7 dis數(shù)組存的為起始點(diǎn)與每個(gè)點(diǎn)的最短距離,比如dis[3]=5,表示起始點(diǎn)與3號(hào)點(diǎn)最短距離為5 8 visit數(shù)組存的為0或者1,1表示已經(jīng)走過這個(gè)點(diǎn)。 9 */ 10 int n,m; 11 int dijstra() 12 { 13 int i,j,pos=1,min,sum=0; 14 memset(visit,0,sizeof(visit));//初始化為.,表示開始都沒走過 15 for(i=1; i<=n; ++i) 16 { 17 dis[i]=map[1][i]; 18 } 19 visit[1]=1; 20 dis[1]=0; 21 for(i=1; i<n; i++) 22 { 23 min=inf; 24 for(j=1; j<=n; ++j) 25 { 26 if(visit[j]==0&&min>dis[j]) 27 { 28 min=dis[j]; 29 pos=j; 30 } 31 } 32 visit[pos]=1;//表示這個(gè)點(diǎn)已經(jīng)走過 33 for(j=1; j<=n; ++j) 34 { 35 if(visit[j]==0&&dis[j]>dis[pos]+map[pos][j])//更新dis的值 36 dis[j]=dis[pos]+map[pos][j]; 37 } 38 } 39 return dis[n]; 40 } 41 int main() 42 { 43 int i,j; 44 while(~scanf("%d%d",&n,&m),n||m)//n表示n個(gè)點(diǎn),m表示m條邊 45 { 46 for(i=1; i<=n; ++i) 47 { 48 for(j=1; j<=n; ++j) 49 { 50 map[i][j]=inf;//開始時(shí)將每條邊賦為最大值 51 } 52 } 53 int a,b,c; 54 for(i=1; i<=m; ++i) 55 { 56 scanf("%d%d%d",&a,&b,&c); 57 if(c<map[a][b])//防止有重邊 58 map[a][b]=map[b][a]=c; 59 } 60 int count=dijstra(); 61 printf("%d\n",count); 62 } 63 return 0; 64 }

鄰接表實(shí)現(xiàn):

1 #include<stdio.h> 2 #include<string.h> 3 #include<vector> 4 #include<algorithm> 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 struct node 8 { 9 int end;///終點(diǎn) 10 int power;///權(quán)值 11 } t; 12 int n;///n為點(diǎn)數(shù) 13 vector<node>q[500001];///鄰接表儲(chǔ)存圖的信息 14 int dis[500001];///距離 15 int vis[500001];///標(biāo)記數(shù)組 16 void Dijkstra(int start,int end) 17 { 18 int i,len,j,pos; 19 memset(vis,0,sizeof(vis)); 20 for(i=0; i<=n; i++) 21 { 22 dis[i]=INF; 23 } 24 len=q[start].size(); 25 for(i=0; i<len; i++) 26 { 27 if(q[start][i].power<dis[q[start][i].end]) 28 { 29 dis[q[start][i].end]=q[start][i].power; 30 } 31 }///從起點(diǎn)開始的dis數(shù)組更新 32 vis[start]=1; 33 for(j=0; j<n-1; j++) 34 { 35 int pos,min=INF; 36 for(i=1; i<=n; i++) 37 { 38 if(vis[i]!=0&&dis[i]<min) 39 { 40 min=dis[i]; 41 pos=i;///找到未訪問節(jié)點(diǎn)中權(quán)值最小的 42 } 43 } 44 vis[pos]=1; 45 len=q[pos].size();///再次更新dis數(shù)組 46 for(j=0; j<len; j++) 47 { 48 if(vis[q[pos][j].end]==0&&dis[q[pos][j].end]>q[pos][j].power+dis[pos]) 49 { 50 dis[q[pos][j].end] = q[pos][j].power+dis[pos]; 51 } 52 } 53 } 54 printf("%d\n",dis[end]); 55 } 56 int main() 57 { 58 int m,i; 59 int begin,end,power; 60 int a,b; 61 while(scanf("%d%d",&n,&m)!=EOF) 62 { 63 for(i=0; i<=n; i++) 64 { 65 q[i].clear();///將victor數(shù)組清空 66 } 67 for(i=0; i<m; i++) 68 { 69 scanf("%d%d%d",&begin,&end,&power);///輸入 70 t.end=end; 71 t.power=power; 72 q[begin].push_back(t); 73 t.end=begin;///無向圖 74 t.power=power; 75 q[end].push_back(t); 76 } 77 scanf("%d%d",&a,&b);///輸入起點(diǎn)與終點(diǎn) 78 Dijkstra(a,b); 79 } 80 return 0; 81 }

?

轉(zhuǎn)載于:https://www.cnblogs.com/wkfvawl/p/9159925.html

總結(jié)

以上是生活随笔為你收集整理的单源最短路——dijkstra算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。