请问谁能告诉我SPFA的算法

来源:学生作业帮助网 编辑:作业帮 时间:2024/05/06 04:02:34
请问谁能告诉我SPFA的算法

请问谁能告诉我SPFA的算法
请问谁能告诉我SPFA的算法

请问谁能告诉我SPFA的算法
很多时候,给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了.
  简洁起见,我们约定有向加权图G不存在负权回路,即最短路径一定存在.当然,我们可以在执行该算法前做一次拓扑排序,以判断是否存在负权回路,但这不是我们讨论的重点.
  我们用数组d记录每个结点的最短路径估计值,而且用邻接表来存储图G.我们采取的方法是松弛:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾.这样不断从队列中取出结点来进行松弛操作,直至队列空为止.
  定理: 只要最短路径存在,上述SPFA算法必定能求出最小值.
  证明:每次将点放入队尾,都是经过松弛操作达到的.换言之,每次的优化将会有某个点v的最短路径估计值d[v]变小.所以算法的执行会使d越来越小.由于我们假定图中不存在负权回路,所以每个结点都有最短路径值.因此,算法不会无限执行下去,随着d值的逐渐变小,直到到达最短路径值时,算法结束,这时的最短路径估计值就是对应结点的最短路径值.(证毕)
  期望的时间复杂度O(ke), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2.
  实现方法:建立一个队列,初始时队列里只有起始点,在建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0).然后执行松弛操作,用队列里有的点去刷新起始点到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后.重复执行直到队列为空
  判断有无负环:如果某个点进入队列的次数超过N次则存在负环 ( 存在负环则无最短路径,如果有负环则会无限松弛,而一个带n个点的图至多松弛n-1次)
标准SPFA过程
  (以求某个结点t到某个结点s的最短路为例,稍加修改即为单源最短路)
Pascal语言代码
  const
  maxp=10000; {最大结点数}
  var {变量定义}
  p,c,s,t:longint; {p,结点数;c,边数;s:起点;t:终点}
  a,b:array[1..maxp,0..maxp] of longint; {a[x,y]存x,y之间边的权;b[x,c]存与x相连的第c个边的另一个结点y}
  d:array[1..2*maxp] of integer; {队列}
  v:array[1..maxp] of boolean; {是否入队的标记}
  dist:array[1..maxp] of longint; {到起点的最短路}
  head,tail:longint; {队首/队尾指针}
  procedure init;
  var i,x,y,z:longint;
  begin
  read(p,c);
  for i := 1 to c do
  begin
  readln(x,y,z); {x,y:一条边的两个结点;z:这条边的权值}
  inc(b[x,0]); b[x,b[x,0]] := y; a[x,y] := z; {b[x,0]:以x为一个结点的边的条数}
  inc(b[y,0]); b[y,b[y,0]] := x; a[y,x] := z;{若为有向图,此句删去.(不删去无法处理负边)}
  end;
  readln(s,t); {读入起点与终点}
  end;
  procedure spfa(s:longint); {SPFA}
  var i,j,now,sum:longint;
  begin
  fillchar(v,sizeof(v),false);
  for j := 1 to p do dist[j]:=maxlongint;
  dist[s]:=0; v[s]:=true;now:=s;{队列的初始状态,s为起点}
  head:=1;tail:= 1;
  d[head]:=s;
  while headdist[now]+a[now,b[now,i]] then
  begin
  dist[b[now,i]]:= dist[now]+a[now,b[now,i]]; {修改最短路}
  if not v[b[now,i]] then {扩展结点入队}
  begin
  tail:=tail+1;
  d[tail mod maxp] := b[now,i];
  v[b[now,i]] := true;
  end;
  end;
  v[now] := false; {释放结点}
  head:=head+1;{出队}
  end;
  end;
  procedure print;
  begin
  writeln(dist[t]);
  end;
  begin
  init;
  spfa(s);
  print;
  end.
C语言代码
  #include
  #define maxint 2139062143
  int a[101][101],dist[101],n;
  void spfa(int s)
  {
  int q[101],v[101],h=0,t=1,x,i;//q为队列,v为Boolean数组,表示结点是否在队列中,h为头指针,t为尾指针
  memset(q,0,sizeof(q));
  memset(v,0,sizeof(v));
  for(i=0;ij;
  if i

请问谁能告诉我SPFA的算法 请问在spfa之前是用什么算法求带负权的图的单源最短路径 求教SPFA算法是什么?麻烦从基础讲起,关于SPFA我只知道是求最短路的. spfa算法与dijsktra算法的应用范围spfa算法与dijsktra除了一个能求带负权的最短路,还有别的不同的应用吗? 请问谁能详细告诉我 素数幻方的算法 跪求! Floyed算法,spfa算法,dij算法各自的优势都在哪里?哪个适用于无向图?哪个适用于负权边? 派的简单算法谁能告诉我,谢谢! 关于Dijkstra、SPFA、Bellman-Ford、Floyed算法的问题总觉得这几个算法的基本框架都差不多,都看重 v[i]>=v[j]+g[i,j] 这个不等式,SPFA是队列优化的Bellman-Ford,但我觉得SPFA如果不用邻接表用起来好像也就 谁能告诉我铝合金门窗的上下方尺寸和玻璃尺寸的算法呀? 谁能告诉我2的29次方,最简单的算法是什么? 谁能告诉我福彩3D的和值准确算法与计算公式 谁能告诉我偶数阶幻方的算法?用文字表述即可. 谁能告诉我下面两题的简便算法-3.228×(-9)-(-3.772)×9+(-1.5)×9(99+15/16)×(-8)我刚刚学习有理数乘除法...还不太明白 谁能告诉我以上题目的简便算法... 谁能告诉我用高斯-约旦消去法来求两矩阵相乘的的算法原理?那如果是这样的话怎么做呢? 铸铁管的重量换算法谁能告诉我130mm外直径15mm厚的球墨铸铁管丨米有多重..紧急 请问谁能告诉我以p开头的英语单词接龙 请问谁能告诉我硫酸铵的用途及性质 请问谁能告诉我这个 符号怎么打出来的?