bellman-ford算法的优化spfa算法

bellman-ford算法能够求带负权值的单源最短路径。但是这个算法的时间复杂度(v*E)还是比较高。所以用spfa算法(SPFA无法处理带负环的图)对其优化(利用队列)。
spfa算法的原理:(引用内容)
如何求得最短路径的长度值? 首先说明,SPFA是一种单源最短路径算法,所以以下所说的“某点的最短路径长度”,指的是“起点到源点的最短路径长度”。

我们记源点为S,由源点到达点i的“当前最短路径”为D[i],开始时将所有D[i]初始化为无穷大,D[S]则初始化为0。算法所要做的,就是在运行过程中,不断尝试减小D[]数组的元素,最终将其中每一个元素减小到实际的最短路径。

过程中,我们要维护一个队列,开始时将源点置于队首,然后反复进行这样的操作,直到队列为空:

(1)从队首取出一个结点u,扫描所有由u结点可以一步到达的结点,具体的扫描过程,随存储方式的不同而不同;

(2)一旦发现有这样一个结点,记为v,满足D[v] > D[u] + w(u, v),则将D[v]的值减小,减小到和D[u] + w(u, v)相等。其中,w(u, v)为图中的边u-v的长度,由于u-v必相邻,所以这个长度一定已知(不然我们得到的也不叫一个完整的图);这种操作叫做松弛。
伪代码:
算法描述
输入设L是用来表示有向图G=(V,E)的邻接表,邻接表元素l是有向图各边的权值,输入各边的权值l(v,k)建立邻接表L.
输出设D数组是记录当前从源点到其余各点的最短路径的值,初始化时D数组的每个元素都为最大值,经过SPFA算法D数组输出各点的最短路径值。
算法的形式算法描述及注释:
1    begin      //算法开始
2    for each v in V do
             Begin
                    For each k∈L[v] do read (l(v,k)); //读入每条边的权值到邻接表
                    QM[v]=0;      //初始化每个顶点是否在队里的标志数组
                    D[v]=MAX;//将最短路径数组初始化为最大值
             End;
3          queue<-v0;
QM[v0]=1;                  //源点v0入queue队
4    D[v0]=0;                  //源点到源点本身的路径值赋值为零
5    while queue not empty do
             Begin
                    W<-queue;    //从queue中取出一个点w
                    QM[w]=0;     //w点出队后,其标志数组元素改为零,表示w点不在队列
6                                      for each j∈L[w] do
7                if D[j]>D[w]+l(w,j) then
                           begin
8                                D[j]=D[w]+l(w,j)  //判断经过w点到j点的路径是比原来的路径D[j]更短后,对j点的路径进行优化
                                  If QM[j]==0 then //只有d[j]的最短路径变化了,j后面的路径才可能会变短。(注意是可能会,尽管如此,我们也要让它入列)
                                  Begin
                                         Queue<-j;
                                         QM[j]=1;       //当j点不在队列里,j入队,并且将QM[j]标志置为1表示j已入队
                                  End
                           End
            End;
9          for each v in V do
begin
             write(D[v]);
end; //优化完成后,D数组存放的就是从源点到各点的最短路径值,可以输出结果
10   end.
 
举个例子:
  一个有向图G ,
 1到2权值为5
 1->3    7
 2->3    -2
 2->4    3
 3->4    4
求源点vo到各顶点的最短路径
代码如下:
#include <iostream>

#include <vector>

#include <queue>

#define mx 99999

#define vmax 20

using namespace std;

int vn ;

int v0 ;

typedef struct
{
 int v , w;
}edge;

vector<edge>g[20] ;

int dist[vmax] ;

int visited[vmax] ;

void spfa()
{

 for(int i = 1; i <= vn; i ++)
  dist[i] = mx ;

 dist[v0] = 0 ;

 queue<int>s ;

 visited[v0] = 1 ;

 s.push(v0);

 while(!s.empty())
 {
  int u = s.front();

  s.pop();

  int temp ;

  visited[u] = 0 ;

  for(int i = 0; i < (int)g[u].size(); i ++)
  {
   temp = g[u][i].w ;
   if(dist[u] != mx && dist[g[u][i].v] > dist[u] + temp)
   {
    dist[g[u][i].v] = dist[u] + temp ;
     if(visited[g[u][i].v] == 0)
     {
      s.push(g[u][i].v) ;
      visited[g[u][i].v] = 1 ;
     }
   }
  }
 }
}
int main()
{
 int m , weight, x , y;

 cin >> vn >> m ;

 edge temp ;

 for(int i = 0; i < m; i ++)
 {
  cin >> x >> y >> weight ;

  temp.v = y ;
  temp.w = weight ;

  g[x].push_back(temp);

 }
 int t ;

 cin >> v0 ;

  spfa();

 while(cin >> t )
 {

  cout << dist[t] << endl ;

 }

 return 0 ;
}

  假若1为源点结果为
 dist[2] = 5
 dist[3] = 3 
 dist[4] = 7
spfa算法还有优化要。大家一起努力吧!



    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/wuhuajunbao/article/details/17041569
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞