最短路(Dijstra算法)


一,問題基本概念:

最短路問題:若網絡中的每條邊都有一個數值(長度,時間,成本等),則找出兩點(通常是源節點和阱節點)之間總權和最小的路徑就是最短路問題。

單源最短路:可以採用Dijkstra算法(但是隻可以求無負權的最短路徑),時間複雜度爲O(|V|^2),如果圖中又負權賄賂,可以採用Bellman-Ford算法(但是它回浪費許多時間做不必要的鬆弛),算法複雜度爲O(|V||E|),還可以用SPFA算法進行優化(使用隊列進行的優化),時間複雜度爲O(k|E|)。

二,各種算法:Dijstra算法:

基本思路:1),參數與返回值:dij算法是單元最短路所以我們需要告訴dij函數你的源點(s)是哪一個結點,然後函數執行完後dis數組中存放的就是s到圖中所有結點的最短距離,如果不連通的話會返回極大值。

                  2),初始化:在初始化過程中我們要定義vis數組--用來記錄已經訪問過的結點,並且清零。然後給dis數組賦初值INF(S點爲0),表示初始情況下源點到除自己之外的所有點都爲無窮大。

                   3),算法主體:我們執行n次循環,每次從dis數組中選出一個值最小的結點標記,並且標記此節點,對這個結點所連接的每一條邊進行鬆弛

                   if(mindis+Map[min][j]<dis[j]&&Map[min][j]!=INF&&vis[j]==0)

                            dis[j]=mindis+Map[min][j];

三,過程:

每次選擇一個未訪問過的到已經訪問過(標記爲Known)的所有點的集合的最短邊,並用這個點進行更新,過程下:

Dv爲最短路,而Pv爲前面的頂點。


1.     初始

V

Known

Dv

Pv

V1

F

0

0

V2

F

0

V3

F

0

V4

F

0

V5

F

0

V6

F

0

V7

F

0

2.     在v1被標記爲已知後的表

V

Known

Dv

Pv

V1

T

0

0

V2

F

2

V1

V3

F

0

V4

F

1

V1

V5

F

0

V6

F

0

V7

F

0

3.     下一步選取v4並且標記爲known,頂點v3,v5,v6,v7是鄰接的頂點,而他們實際上都需要調整。如表所示:

V

Known

Dv

Pv

V1

T

0

0

V2

F

2

V1

V3

F

3

V4

V4

T

1

V1

V5

F

3

V4

V6

F

9

V4

V7

F

5

V4

4.     接下來選取v2,v4是鄰接點,但已經是known的,不需要調整,v5是鄰接的點但不做調整,因爲經過v2的值爲2+10=12而長爲3的路徑已經是已知的。

V

Known

Dv

Pv

V1

T

0

0

V2

T

2

V1

V3

F

3

V4

V4

T

1

V1

V5

F

3

V4

V6

F

9

V4

V7

F

5

V4

5.     接下來選取v5,值爲3,v7 3+6>5不需調整,然後選取v3,對v6的距離下調到3+5=8

V

Known

Dv

Pv

V1

T

0

0

V2

T

2

V1

V3

T

3

V4

V4

T

1

V1

V5

T

3

V4

V6

F

8

V3

V7

F

5

V4

6.     再選下一個頂點是v7,v6變爲5+1=6

V

Known

Dv

Pv

V1

T

0

0

V2

T

2

V1

V3

T

3

V4

V4

T

1

V1

V5

T

3

V4

V6

F

6

V7

V7

T

5

V4

7.     最後選取v6

V

Known

Dv

Pv

V1

T

0

0

V2

T

2

V1

V3

T

3

V4

V4

T

1

V1

V5

T

3

V4

V6

T

6

V7

V7

T



四,算法所有代碼:

1 /****************************************
 2      Dijkstra O(n^2) 單元最短路算法
 3      鄰接矩陣        
 4                  
 5 *****************************************/
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <string.h>
 9 #define INF 0x3f3f3f3f
10 #define LEN 1010
11 using namespace std;
12 
13 int Map[LEN][LEN], dis[LEN], n, m;
14 
15 void Dijkstra(int s)
16 {
17     int vis[LEN] = {0};
18     for(int i=1; i<=n; i++)
19         dis[i] = INF;//初始化爲最大值
20     dis[s] = 0;
21     for(int i=0; i<n ;i++)
22     {
23         int min, mindis = INF;
24         for(int j=1; j<=n; j++)
25             if(dis[j]<mindis && vis[j] == 0)//如果它的距離小於INF,並且該點沒有被遍歷過
26             {
27                 mindis = dis[j];
28                 min = j;//權值與最大值比較,若比他小,則進行賦值,並記錄下該點
29             }
30         vis[min] = 1;
31         for(int j=1; j<=n; j++)
32             if(mindis+Map[min][j]<dis[j] && Map[min][j]!=INF && vis[j]==0)//進行鬆弛操作
33                 dis[j] = mindis+Map[min][j];
34     }
35 }
36 
37 
38 int main()
39 {
40 //    freopen("in.txt", "r", stdin);
41     return 0;
42 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章