單源最短路徑演算法
1.單源最短路徑以及Dijsktra演算法
2.多源最短路徑以及Floyd演算法
1.1單源最短路徑:
即從一個特定的點出發,尋找這個點到其他點的最短路徑
對於一個無權圖,BFS演算法就可以了。但是對於加權圖,BFS行不通
1.2 Dijkstra(迪傑斯特拉):針對加權有向圖、單源最短路徑
dijkstra通過一個簡單的動態規劃思想來求最短路徑。
(假設求從點s出的的單源最短路徑)記D(w)為點s到點w的的最短路徑,其狀態轉移方程:
D(w) = min{D(u)+w(u,w)};
u是還沒有被訪問過的,距離s距離最小的點。
順次處理所有的點
虛擬碼:
for i:0->n-1
do
v = minV(G,D) //v是還沒有被訪問過的點中,離s距離最小的點
set V visit
for(w=G->first(v);w<G->n;w=G->next(v,w)) //更新所有能通過v到達的點的距離
do
if D[w]>D[v]+w(v,w)
D[W] = D[v]+w(v,w)
2.多源最短路徑以及Floyd演算法
2.1多源最短路徑:求任意兩個點之間的最短路徑
2.2Floyd演算法 (相關:UVa576)
插點+動態規劃
d(i,j) = min{d(i,j),d(i,k)+d(k,j)}
即i,j兩點之間的最短路徑等於 i,j兩點之間直接距離(如果i,j之間存在邊的話)與i經過點k到j的距離中 最小的那一個
以下圖為例
對應距離矩陣:
現在求兩個點i,j兩點經過點1時兩點的最短路徑,核心程式碼如下:
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(e[i][j]>e[i][1]+e[1][j]) e[i][j]=e[i][1]+e[1][j];
先求兩個點i,j經過點1、2時兩點的最短路徑,核心程式碼如下
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j]>e[i][1]+e[1][j])
e[i][j]=e[i][1]+e[1][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j]>e[i][2]+e[2][j])
e[i][j]=e[i][2]+e[2][j];
我們最終要求的是i,j經過點1,2。。。n時兩點的最短路徑,因此程式碼如下:
for(int k=1;k<=n;k++){
for(int i=1;i=<n;i++)
for(int j=1;j<=n;j++)
if(e[i][j]>e[i][1]+e[1][j])
e[i][j]=e[i][1]+e[1][j];
}
要注意,上述兩種演算法都不適用於權值有負數的圖中
因為可能構成負權迴路,而負權迴路是沒有最小路徑的。