1. 程式人生 > >單源最短路徑演算法

單源最短路徑演算法

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];
}

要注意,上述兩種演算法都不適用於權值有負數的圖中

因為可能構成負權迴路,而負權迴路是沒有最小路徑的。