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

11 篇文章 0 订阅
4 篇文章 0 订阅
#include  < iostream >
#include 
< vector >
#include 
<set>
using   namespace  std;

typedef vector 
< int >  vi;
typedef pair 
< int int >  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 
< int int >  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]);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值