好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Dijkstra算法 (迪杰斯特拉)

定义

  Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

原理

  设图 G=(V,E) 所有顶点的集合为 V,起点为 S,最短路径树中包含的顶点集合为 S。在各计算步骤中,我们将选出最短路径树的边和顶点并将其添加至S。

  对于各顶点 i,设仅经由S内的顶点的 s 到 i 的最短路径成本为 d[i], i 在最短路径树中的父节点为 p[i]。

  ①初始状态下将 S 置空。

      初始化 s 的 d[s]=0;除 s 外,所有属于 V 的顶点 i 的 d[i]= ∞。

  ②循环进行下述处理,直至 S=V 为止。

      从 V-S 中选出 d[u] 最小的顶点 u。

     将 u 添加至 S,同时将与 u 相邻且属于 V-S 的所有顶点 v 的值按照下述方式更新

     if(d[u] + w(u,v) < d[v])

        d[v] = d[u] + w(u,v) ,  p[v] = u ;

  ❗ 显然迪杰斯特拉算法并不能处理负权图。下图中A->B的最短路应为 3=8-5,但用此算法算出来的A->B的最短路为7。

 

  迪杰斯特拉最短路径算法和普利姆算法贼像。:)

实现

 

 

 

原算法

 #include<bits/stdc++.h>
 using   namespace   std;
  const   int  maxn= 1005  ;
  const   int  inf= 0x3f3f3f3f  ;
  struct   node
{
    int   v,w;
  node(){}
  node(  int  a, int   b)
  {v =a;w= b;}
};
vector <node>  e[maxn];
  int   n,m;
  void   dij();
  int   main()
{
    int   i,u,v,w;
  scanf(  "  %d%d  " ,&n,& m);
    for (i= 1 ;i<=m;i++ )
  {
    scanf(  "  %d%d%d  " ,&u,&v,& w);
    e[u].push_back(node(v,w));
  }
  dij();
  system(  "  pause  "  );
    return   0  ;
}
  void   dij()
{
    int  dis[maxn],vis[maxn]={ 0  },i,j,mmin,f;
  fill(dis,dis + maxn,inf);
  dis[  1 ]= 0  ;
    for (i= 1 ;i<=n;i++ )
  {
    mmin = inf;
      for (j= 1 ;j<=n;j++ )
        if (!vis[j]&&dis[j]< mmin)
        mmin =dis[f= j];
    
    vis[f] = 1  ;
      for (j= 0 ;j<e[f].size();j++ )
    {
        if (dis[e[f][j].v]>dis[f]+ e[f][j].w)
        dis[e[f][j].v] =dis[f]+ e[f][j].w;
    }
  }
    for (j= 1 ;j<=n;j++ )
    printf(  "  1->%d   %d\n  "  ,j,dis[j]);
}  

优先队列优化

 #include<bits/stdc++.h>
 using   namespace   std;
  const   int  maxn= 1005  ;
  const   int  inf= 0x3f3f3f3f  ;
  struct   node
{
    int   v,w;
  node(){}
  node(  int  a, int   b)
  {v =a;w= b;}
    bool   operator  <( const  node &n)  const  
  {  return  w> n.w;}
};
vector <node>  e[maxn];
  int   n,m;
  void   dij_queue();
  int   main()
{
    int   i,u,v,w;
  scanf(  "  %d%d  " ,&n,& m);
    for (i= 1 ;i<=m;i++ )
  {
    scanf(  "  %d%d%d  " ,&u,&v,& w);
    e[u].push_back(node(v,w));
  }
  dij_queue();
  system(  "  pause  "  );
    return   0  ;
}
  void   dij_queue()
{
    int  dis[maxn],vis[maxn]={ 0  },u,v,w,i;
  node p;
  priority_queue <node>  que;
  que.push(node(  1 , 0  ));
  fill(dis,dis + maxn,inf);
  dis[  1 ]= 0  ;
    while (! que.empty())
  {
    p = que.top();que.pop();
    u = p.v;
      if (vis[u])  continue  ;
    vis[u] = 1  ;
      for (i= 0 ;i<e[u].size();i++ )
    {
     w =e[u][i].w;v= e[u][i].v;
       if (!vis[v]&&dis[v]>dis[u]+ w)
      {
        dis[v] =dis[u]+ w;
        que.push(node(v,dis[v]));
      }
    }
  }
    for (i= 1 ;i<=n;i++ )
    printf(  "  1->%d   %d\n  "  ,i,dis[i]);
}  

挑战程序设计竞赛(第2版)

查看更多关于Dijkstra算法 (迪杰斯特拉)的详细内容...

  阅读:48次