hdu 1874 Dijkstra算法

先貼個網上找的比較通俗易懂的教程:php

2.1  Dijkstra算法(非負權,使用於有向圖和無向圖)ios

  Dijkstra算法是典型最短路算法,用於計算一個節點到其餘全部節點的最短路徑。主要特色是以起始點爲中心向外層層擴展,直到擴展到終點爲止。Dijkstra算法能得出最短路徑的最優解,但因爲它遍歷計算的節點不少,因此效率低。算法

Dijkstra算法是頗有表明性的最短路算法,在不少專業課程中都做爲基本內容有詳細的介紹,如數據結構,圖論,運籌學等等。 數據結構

2.2  Dijkstra算法思想spa

Dijkstra算法思想爲:設G=(V,E)是一個帶權有向圖,把圖中頂點集合V分紅兩組,第一組爲已求出最短路徑的頂點集合(用S表示,初始時S中只有一個源點,之後每求得一條最短路徑 , 就將 加入到集合S中,直到所有頂點都加入到S中,算法就結束了),第二組爲其他未肯定最短路徑的頂點集合(用U表示),按最短路徑長度的遞增次序依次把第二組的頂點加入S中。在加入的過程當中,總保持從源點v到S中各頂點的最短路徑長度不大於從源點v到U中任何頂點的最短路徑長度。此外,每一個頂點對應一個距離,S中的頂點的距離就是從v到此頂點的最短路徑長度,U中的頂點的距離,是從v到此頂點只包括S中的頂點爲中間頂點的當前最短路徑長度。.net

2.3  Dijkstra算法具體步驟  code

1)初始時,S只包含源點,即S=,v的距離爲0。U包含除v外的其餘頂點,U中頂點u距離爲邊上的權(若v與u有邊)或 )(若u不是v的出邊鄰接點)。blog

(2)從U中選取一個距離v最小的頂點k,把k,加入S中(該選定的距離就是v到k的最短路徑長度)。教程

(3)以k爲新考慮的中間點,修改U中各頂點的距離;若從源點v到頂點u(u U)的距離(通過頂點k)比原來距離(不通過頂點k)短,則修改頂點u的距離值,修改後的距離值的頂點k的距離加上邊上的權。v8

(4)重複步驟(2)和(3)直到全部頂點都包含在S中。

2.4  Dijkstra算法舉例說明

以下圖,設A爲源點,求A到其餘各頂點(B、C、D、E、F)的最短路徑。線上所標註爲相鄰線段之間的距離,即權值。(注:此圖爲隨意所畫,其相鄰頂點間的距離與圖中的目視長度不能一一對等)

 

圖一:Dijkstra無向圖

 最短路徑之Dijkstra算法詳細講解 - 綠巖 - 永遠的綠巖

算法執行步驟以下表:

最短路徑之Dijkstra算法詳細講解 - 綠巖 - 永遠的綠巖

 

 

而後是僞代碼:

清除全部點標記

d[0] = 0,其餘d[i] = INF

循環n次

{

  在全部未標記節點中,選出d值最小的結點x

  標記x結點

  對於從x出發的全部邊(x,y),更新d[y] = min(d[y], d[x] + w(x,y))

}

假設起始結點爲start,它到結點i的路徑長d[i], 未標記結點v[i] = 0,已標記v[i]=1.
w[x][y] = INF表示邊(x,y)不存在
模板代碼:

memset(v, 0, sizeof(v));
for (int i = 0; i < n; ++i)
    d[i] = (i == start ? 0 : INF);
for (int i = 0; i < n; ++i)
{
    int x, m = INF;
    for (int y = 0; y < n; ++y)
        if (!v[y] && d[y] <= m)
        {
            x = y;
            m = d[y];
        }
    v[x] = 1;
    for (int y = 0; y < n; ++y)
        d[y] = min(d[y], d[x] + w[x][y]);
}

用一道題目練練:

http://acm.hdu.edu.cn/showproblem.php?pid=1874

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 const int INF = INT_MAX / 2;
 5 int main()
 6 {
 7     int n, m;
 8     while (scanf("%d %d", &n, &m) != EOF)
 9     {
10         int w[n][n];
11         for (int i = 0; i < n; ++i)
12             for (int j = 0; j < n; ++j)
13                 w[i][j] = INF;
14         int a, b, c;
15         for (int i = 0; i < m; ++i)
16         {
17             scanf("%d %d %d", &a, &b, &c);
18             if (c < w[a][b])                //一個坑,無向圖可能有多條路,求最短的
19             w[a][b] = w[b][a] = c;
20         }
21         int start, end;
22         scanf("%d %d", &start, &end);
23         int d[n], v[n];
24         for (int i = 0; i < n; ++i)
25             v[i] = 0;
26         for (int i = 0; i < n; ++i)
27             d[i] = (i == start ? 0 : INF);
28         for (int i = 0; i < n; ++i)
29         {
30             int x, m = INF;
31             for (int y = 0; y < n; ++y)
32                 if (!v[y] && d[y] <= m)
33                     m = d[x=y];
34             v[x] = 1;
35             for (int y = 0; y < n; ++y)
36                 d[y] = d[y] < d[x] + w[x][y] ? d[y] : d[x] + w[x][y];
37         }
38         if (d[end] != INF)
39             printf("%d\n", d[end]);
40         else
41             printf("-1\n");
42     }
43     return 0;
44 }
相關文章
相關標籤/搜索