最短路 Dijkstra學習筆記

2022-05-26 20:30:10 字數 3697 閱讀 8935

最近蒟蒻的自己重新學習了一遍最短路,也算有些體會,記錄下來。

首先引入問題:在一張圖中,從某一頂點出發,沿圖的邊到達定乙個頂點所經過的路徑中,各邊權值和最小的一條路徑。

解決該問題的演算法有:dijkstra演算法,

bellman-ford

演算法,floyd

演算法和spfa

演算法介紹:dijkstra演算法是單源最短路演算法的一種,用於求出發節點到所有可達節點的最短路長度。

限制:路徑權值必須為非負數無負權迴路單源最短路

演算法思想:dijkstra演算法運用了貪心的思想,通過不斷尋找最短距離的點,用以該點為弧尾的點的邊更新其他的路徑(鬆弛)。設起點為

start

,終點為

end,

start-->end

的最短路徑只有兩種情況。

1、start--->end   (從起點到終點直接為最短路徑)

2、start--->v1--->v2...--->end (從起點通過其他的點到達終點的路徑)

演算法步驟:

把頂點v分成兩組:

s:已經求出最短路徑的頂點集合

t=v-s:尚未確定最短路徑的頂點集合

1、初始時:令s=  t=  t

中的頂點對應的距離值若存在

,則為該邊的權值,若不存在則為

inf(正無窮)

2、從t中選取乙個距離最小的頂點

w,將該點加入集合

s中。並用該點對

t中頂點的距離進行修改:若加入

w作為中間頂點(

v0-->w-->vn),

該路徑的距離比不加入

w的路徑更短,則修改此距離值。

3、重複上述步驟,知道s中包含所有頂點,即

s=v為止

演算法實現過程中需要兩個陣列

1、dist陣列記錄源點到每個點的最短路徑大小

2、vis陣列記錄該點是否已經在集合

s中(即是否已經找到到該點的最短路徑)

演算法過程(手動模擬,qaq醜字不要介意)

這裡用一道最短路的模板題來展示該演算法的**。(poj - 2387 til the cows come home)

題意:給你n個點,給出a到b的距離,a,b邊是可以互想抵達的,求1到n的最短距離。實質:n個頂點m條邊的無向圖,求1到n的最短路徑。

//

鄰接矩陣存圖版本

#include#include

#include

using

namespace

std;

const

int max=1005

;const

int inf=0x3f3f3f3f

; int t,n; //

邊數 點數

int map[max][max]; //

鄰接矩陣存圖

int dist[max]; //

dist陣列存源點到各個點的最短路徑

bool vis[max]; //

標記是否找到最小值(是否在集合s中)

void dij(int

start)

dist[start]=0; //

源點到源點的值為0

int min=inf,pos; //

尋找dist陣列中最小值,並記錄其所在的點

for(int i=1;i<=n;i++)

}

vis[pos]=true; //

將該點加入集合s中

for(int j=1;j<=n;j++) //

用該點為弧尾的邊進行鬆弛操作

} } int

main()

dij(

1); //

以1為源點進行dijkstra

printf("

%d\n

",dist[n]);

}return0;

}

//

鄰接表存圖

#include#include

#include

#include

using

namespace

std;

const

int max=1005

;const

int inf=0x3f3f3f3f

;int

t,n,a,b,len;

intdist[max];

bool

vis[max];

struct

point

;vector

e[max];

void dij(int

start)

dist[start]=0; //

源點到源點距離為0

intmin,pos;

for(int i=1;i<=n;i++)

}vis[pos]=true

;

for(int j=0;j//

用找到的點為弧尾的邊進行鬆弛

}}int

main()

dij(1);

printf(

"%d\n

",dist[n]);

}return0;

}

//

鏈式前向星存圖

#include#include

#include

using

namespace

std;

const

int maxn=4009

;const

int max=1009

; const

int inf=0x3f3f3f3f

;int head[max],cnt=0

;int

t,n,a,b,len;

intdist[max];

bool

vis[max];

struct

edgeedge[maxn];

inline

void add(int u,int v,int

w)void dij(int

start)

dist[start]=0

;

intmin,pos;

for(int i=1;i<=n;i++)

}vis[pos]=true

;

for(int i=head[pos];i!=-1;i=edge[i].next)

}}int

main()

dij(1);

printf(

"%d\n

",dist[n]);

}return0;

}

參考:

Dijkstra學習筆記 單源最短路

dijkstra是通過貪心來進行實現的。所以不能判定有負邊的圖。看一下這張圖,我們從1 11號點開始遍歷,且令dis ti dist i disti 為第i ii個點到1 11好點的最短路徑。首先我們把已知最短路的點設為長方形,未知的設為圓形即可,那麼一號點就是已知的,及dis t1 0 dist ...

最短路徑演算法(Dijkstra)學習筆記

include include using namespace std define vex 5 定義結點的個數 define maxpoint 100 double graph maxpoint 鄰接矩陣 inti,j intmain b maxpoint int d vex p vex 定義陣列...

Dijkstra 最短路徑

dijkstra 最短路徑 針對有向圖,不支援負權值 圖的相鄰矩陣表示方法,還要用到最小值堆 include include define unvisited 0 define visited 1 define infinite 9999 設定最大值 define n 5 定義圖的頂點數 using...