单源最短路 Dijkstra 算法 C++高效实现

来源:互联网 发布:手机变声软件 编辑:程序博客网 时间:2024/04/29 22:20
#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]);
}
原创粉丝点击