Dijkstra演算法 單源最短路 堆優化

2021-10-05 20:34:20 字數 3400 閱讀 4396

每次找到離源點最近的乙個頂點,然後以該頂點為中心向下擴充套件,最終得到源點到其餘所有點的最短路徑。

說明:dis陣列儲存離源點的所有點的最短路徑,比如源點是1,dis[2]=3,表示頂點2離源點的最短路徑為2

執行步驟:

1.將所有點的頂點分為兩部分:已知最短路徑集合p和未知最短路徑的集合q。最開始,已知最短路徑的頂點集合p只有源點乙個頂點。我們這裡用乙個book陣列來記錄哪些點在集合p中。例如當對於某個頂點i,如果book[i]為true則表示這個頂點在集合p中,如果book[i]為false則表示在集合q中。

2.設定源點s到自己的最短路徑為0即dis[s]=0;若存在源點能直接到達頂點i,則把dis[i]設為e[s][i].同時把其他其他所有(源點不能直接到達的)頂點的最短路徑設為無窮大

3.在集合q的所有頂點中選擇乙個離源點s最近的頂點u(即dis[u]最小)加入到集合p.並考察所有以點u為起點的邊,對每一條邊進行鬆弛操作。例如存在一條從u到v的邊,那麼可以通過將邊u→v新增到尾部來拓展一條從s到v的路徑,這條路徑的長度是dis[u]+e[u][v].如果這個值比目前已知的dis[v]的值最小,我們可以用新值來替代當前dis[v]中的值

4.重複第三步,如果集合q為空,演算法結束。最終dis陣列中的值就是源點到所有頂點的最短路徑

輸入我們採用鄰接矩陣:

用e陣列來儲存圖

scanf

("%d %d"

,&n,

&m,&cnt)

;//n個頂點,m條邊,cnt表示源點

for(

int i=

1;i<=n;i++

)else}}

int t1,t2,t3;

for(

int i=

1;i<=m;i++

)

初始化dis陣列(也就是步驟2):

for

(int i=

1;i<=n;i++

)

初始化book陣列:

這裡我開到了全域性變數,所以所有值預設為false(還未求出最短路徑)

我們只需要將源點的book賦值為true即可,表示源點已求出最短路徑

book[cnt]

=true

;//初始化book陣列

核心演算法:

//dijkstra演算法核心

//實現找出離源點最近的點

for(

int i=

1;i<=n-

1;i++)}

book[u]

=true

;//已經找出來離遠點最近的點,將此點設為訪問過

//以下實現鬆弛操作

for(

int v=

1;v<=n;v++)}

}}

完整**:

/*

測試資料 :第一行n,m,cnt,接下來是m條邊

6 9 1

1 2 1

1 3 12

2 3 9

2 4 3

3 5 5

4 3 4

4 5 13

4 6 15

5 6 4

*/#include

int e[10]

[10];

//鄰接矩陣存放圖

int dis[10]

;//用來記錄所有點離原點的最短路徑

bool book[10]

;//記錄點有沒有被訪問過

int n,m,min,inf=

99999999

,cnt;

intmain()

else}}

int t1,t2,t3;

for(

int i=

1;i<=m;i++

)for

(int i=

1;i<=n;i++

)/*for( i=1;i<=n;i++)printf("\n");

}*/book[cnt]

=true

;//初始化book陣列

int min,u;

//dijkstra演算法核心

for(

int i=

1;i<=n-

1;i++)}

book[u]

=true

;for

(int v=

1;v<=n;v++)}

}}for(

int i=

1;i<=n;i++

)return0;

}

該演算法大量的時間花在前期尋找最近的點這一步,其實可以直接使用小頂堆進行優化

/*

測試資料

6 9 1

1 2 1

1 3 12

2 3 9

2 4 3

3 5 5

4 3 4

4 5 13

4 6 15

5 6 4

0 1 8 4 13 17

*/#include

#include

#include

#include

using

namespace std;

const

int inf =

2147483647

;int n,m,start,dis[

10005

],vis[

10005];

struct node};

vector ve[

10005];

//鄰接表存圖

priority_queueint,

int>

,vectorint,

int>

>

,greaterint,

int>

>

> que;

//小頂堆

intmain()

//初始化dis

for(

int i=

1;i<=n;i++)

dis[start]=0

;//初始化佇列

que.

push

(make_pair(0

,start));

//dijkstra演算法

while

(!que.

empty()

)}}for

(int i=

1;i<=n;i++

)return0;

}

單源最短路 Dijkstra演算法

前提 沒有負邊 如果有負邊,可以用此方法檢查是否有負圈 const max v max v 表示邊的權重值 d max v 儲存從起點到每個點的總權重值 bool used max v 表示當前點是否已經訪問完畢 思想 找到乙個已經確定最短距離的點,更新跟它相鄰的點,之後這個點就不用關心了。起點最短...

單源最短路演算法 Dijkstra

dijkstra演算法是單源最短路演算法,可以求解不帶負權邊的圖中,從源點s到其它所有點的最短路。時間複雜度近似o n 2 可以用堆優化。一般用鄰接表,也可用鄰接矩陣。在稠密圖上會有較好的效能表現。include include using namespace std int s,t,n,m,las...

單源最短路 Dijkstra演算法

本文 自王陸的文字,僅作學習使用。dijkstra 迪傑斯特拉 演算法是典型的單源最短路徑演算法,用於計算乙個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。問題描述 在無向圖 g v,e 中,假設每條邊 e i 的長度為 w i 找到由頂點 v0 到...