單源最短路 Dijkstra 算法 C++高效實現

#include <iostream>
#include 
<vector>
#include 
<set>
using namespace std;

typedef vector 
<int> vi;
typedef pair 
<intint> ii;
typedef vector 
<ii> vii;
typedef vector 
<vii> vvii;
const int INF = 0x7FFFFFFF;

// 創建一個賦權鄰接表(參考樣例,具體問題可能需要適當修改,特別是對於無向圖)
// n 爲頂點數(從 0 開始標記),e 爲邊數
vvii AVLmaker (int n, int e)
{
    vvii G (n);
    
for (int i = 0; i < e; i ++)
        {
        
int v1, v2, d;
        cin 
>> v1 >> v2 >> d;
        G [v1].push_back (ii (v2, d));
        }
    
return G;
}

// s 爲源點,返回 s 到各點的最短路長度,INF 表示無法到達
vi Dijkstra (const vvii& G, int s)    // vvii G is the adjacent vertices list of the weighted directed graph
{    
    
int n = G.size ();
    vi D (n, INF);
    
set <ii> Q;
    D [s] 
= 0;
    Q.insert (ii (
0, s));
    
while (!Q.empty ())
        {
        ii p 
= *Q.begin ();
        Q.erase (Q.begin ());
        
int d = p.first, v = p.second;
        
for (int i = 0, j = G [v].size (); i < j; i ++)
            {
            
int v2 = G [v] [i].first, d = G [v] [i].second;
            
if (D [v2] > D [v] + d)    // notice that D [v] != INF && d != INF
                {
                
if (D [v2] != INF)
                    {
                    Q.erase (Q.find (ii (D [v2], v2)));
                    }
                D [v2] 
= D [v] + d;
                Q.insert (ii (D [v2], v2));
                }
            }
        }
    
return D;
}
 
參考來源:
TopCoder tutorials : Power up C++ with the Standard Template Library : Part II: Advanced Uses : Dijkstra by set

PS:
這個是圖論裏最基本的問題,今天終於搞定了,爲往日浪費的光陰懺悔。。Orz。。
這個實現的確很高效,在 Sicily 的某題的提交結果:
Run ID      User Name      Problem      Language      Status      Run Time      Run Memory      Submit Time
92839       rappizit     1387     C++     Accepted     0 sec     252 KB     2007-10-31 20:20:12

===============================================================================
2007-11-28 Update:
implemented via priority_queue, faster but use more memory, and add a statement : if (v ==t) break;
#include <vector>
#include 
<queue>
#include 
<functional>
using namespace std;

typedef vector 
<int> vi;
typedef pair 
<intint> ii;
typedef vector 
<ii> vii;
typedef vector 
<vii> vvii;

int Dijkstra (const vvii& G, int s, int t)
{
    
const int INF = 0x7FFFFFFF;
    
int n = G.size ();
    vi D (n, INF);
    priority_queue 
< ii, vector <ii>, greater <ii> > Q;
    D [s] 
= 0;
    Q.push (ii (
0, s));
    
while (Q.size ())
        {
        ii p 
= Q.top ();
        Q.pop ();
        
int d = p.first, v = p.second;
        
if (v == t) break;
        
if (D [v] < d) continue;
        
for (int i = 0, j = G [v].size (); i < j; i ++)
            {
            
int v2 = G [v] [i].first, d = G [v] [i].second;
            
if (D [v2] > D [v] + d)    // D [v] != INF && d != INF
                {
                D [v2] 
= D [v] + d;
                Q.push (ii (D [v2], v2));
                }
            }
        }
    
return (D [t] == INF ? -1 : D [t]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章