SPFA算法
  求单源最短路的SPFA算法的全称是:Shortest Path Faster
Algorithm
 最短路径快速算法-SPFA算法是西南交通大学段凡丁于1994年发表的。
  适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了。 我们约定有向加权图G不存在负权回路,即最短路径一定存在。当然,我们可以在执行该算法前做一次拓扑排序,以判断是否存在负权回路,但这不是我们讨论的重点。
  算法思想:我们用数组d记录每个结点的最短路径估计值,用邻接表来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。


因为SPFA没有向迪杰斯塔拉算法那样,寻找dist[]的最小值,所以重复入队,更新dis[]的最小值,因为这个点本身dis[]的变化,会影响到与之邻接的点,所以要重复入队。
标程一:
const
int INF =
999999;
int 
map
[MAXN][MAXN];
//map[i,j]为初始输入的ij的距离,未知的map[i,j]=INF;
int 
dis
[MAXN];//源点Si的最短路
char vst[MAXN];//是否在队列中的标记
int     
Q[MAXN];
//队列
//
参数n表示结点数,s表示源点
int SPFA(int n,
int s)
{  int
i, pri, end, p, t;
// pri是队列头结点,end是队列尾结点
   
memset(vst,
0, sizeof(vst));//初始化
   
for(int
i=0; i<</b>MAXN; ++i)
       
Q
[i] =
0;//初始化队列为空
   
for (i=0; i<</b>n; i++)
       
dis
[i] =
INF;//初始化源点到I的值为最大值
   
dis
[s] =
0;//源点为0
   
vst
[s] =
1;//标记为已入队
Q[0] =
s;//源点入队
pri = 0; end
= 1;//队首队尾赋值
   
while (pri
<</b> end)
   
{
       
p
= Q[pri];//取队首元素
       
for (i=0; i<</b>n; ++i)
//更新dis
       
{ if (dis[p]+map[p][i] <</b> dis[i])
           
{ 
dis
[i] =
dis[p]+map[p][i];
               
if (!vst[i])    
//
未在队列中
               
{ 
Q
[end++]
= i;
                  
vst
[i] =
1;
               
}
           
}
       
}
       
vst
[p] =
0;   //

置出队的点为未标记

       
pri
++;
   
}
   
return 1;
}
标程二:
int num[999999]; //记录入队次数
 
void spfa(int s)  // 
初始结点s,即为起点,若目标结点t,则输出dict[t]。
{  
init_data(s);
   
int
head = 0, tail = 1;  
   
int path[Max];  // 
可增加一个path[]数组来记录最后s到t的路径。
    queue[0]
= s; //que.push(s);
 
   
dict[s] = 0;
   
while
(tail >
head)//(!que.empty())
 
    {
int
u = queue[head];//int
u=que.front();  
//que.pop();
       
vis[u] = true;
 
       
for
(i = 1; i <= n; i ++)
       
{ if
(dict[i] > dict[u] +
edge[u][i])
           
{  dict[i] = dict[u] +
edge[u][i];
              
path[i] = u;
 
              
num[i]++
              
if(num[i]>=n) return
1;//判断是否有负权值……
              
if
(!vis[i]) 
//  对以前没有访问过的顶点,加入队列中。
               
{  vis[i] = true;
                  
queue[tail] = i;// que.push(i);
                  
tail
++;                      

 
               
}
            
}
        
}
        
vis[u] = false;  // 
记得把出队列的顶点的vis[]置为false。
       
head ++;
 
   
}
}
判断负权回路
num[i]>=n的原因,即使所有的点更新都会让i入队的话,才只有n-1次,这时一定是最小值了,入队n次,一定有负权回路

最短路径:我的理解--SPFA算法的更多相关文章

  1. SPFA算法——最短路径

    粗略讲讲SPFA算法的原理,SPFA算法是1994年西南交通大学段凡丁提出 是一种求单源最短路的算法 算法中需要用到的主要变量 int n;  //表示n个点,从1到n标号 int s,t;  //s ...

  2. 【算法】单元最短路径之Bellman-Ford算法和SPFA算法

    SPFA是经过对列优化的bellman-Ford算法,因此,在学习SPFA算法之前,先学习下bellman-Ford算法. bellman-Ford算法是一种通过松弛操作计算最短路的算法. 适用条件 ...

  3. (转)SPFA算法

    原文地址:http://www.cnblogs.com/scau20110726/archive/2012/11/18/2776124.html 粗略讲讲SPFA算法的原理,SPFA算法是1994年西 ...

  4. SPFA 算法(剪辑)(学习!)

    SPFA算法 单源最短路径的算法最常用的是Dijkstra,些算法从时间复杂度来说为O(n^2),但是面对含有负权植的图来说就无能为力了,此时 Dellman-ford算法就有用了,这咱算法是采用的是 ...

  5. 转载:SPFA算法学习

    转载地址:http://www.cnblogs.com/scau20110726/archive/2012/11/18/2776124.html 粗略讲讲SPFA算法的原理,SPFA算法是1994年西 ...

  6. 数据结构与算法--最短路径之Bellman算法、SPFA算法

    数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...

  7. (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍

    这一篇博客以一些OJ上的题目为载体.整理一下最短路径算法.会陆续的更新... 一.多源最短路算法--floyd算法 floyd算法主要用于求随意两点间的最短路径.也成最短最短路径问题. 核心代码: / ...

  8. 最短路径问题的Dijkstra和SPFA算法总结

    Dijkstra算法: 解决带非负权重图的单元最短路径问题.时间复杂度为O(V*V+E) 算法精髓:维持一组节点集合S,从源节点到该集合中的点的最短路径已被找到,算法重复从剩余的节点集V-S中选择最短 ...

  9. 最短路径--SPFA 算法

    适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径一 ...

随机推荐

  1. 深入理解Spring系列之一:开篇

    转载 https://mp.weixin.qq.com/s?__biz=MzI0NjUxNTY5Nw==&mid=2247483810&idx=1&sn=a2df14fdb63 ...

  2. 利用__attribute__((section()))构建初始化函数表【转】

    转自: https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=2652663356&idx=1&sn=7797629530 ...

  3. React 16 源码瞎几把解读 【前戏】 为啥组件外面非得包个标签?

    〇.看前准备 1.自行clone react最新代码 2.自行搭建一个能跑react的test项目 一.看表面:那些插件 如何解析JSX 有如下一段代码: // ---- hearder.jsx 组件 ...

  4. openjudge-NOI 2.6-2728 摘花生

    题目链接:http://noi.openjudge.cn/ch0206/2728/ 题解: 某一个点只能从其左边或者上边走过来 f[i][j]存储(i,j)这个点上的结果,即f[i][j]=max(f ...

  5. [转载]FFmpeg完美入门[3] - FFmpeg功能及使用说明

    1 ffplay对多媒体的支持能力验证 一.视频3gp 177X144 支持播放,在windows下播放正常,但是在linux下面偶有BUG 如果发现画面无法显示而声音可以播放的情况下可以试着切换全屏 ...

  6. go语言入门(二)

    Go 语言变量 Go 语言变量名由字母.数字.下划线组成,其中首个字母不能为数字. 声明变量的一般形式是使用 var 关键字: var identifier type 变量声明 第一种,指定变量类型, ...

  7. java中参数传递--值传递,引用传递

    java中的参数传递——值传递.引用传递   参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用. ...

  8. EL(表达式)语言的几种运算符

    1.EL的基本语法 (1)EL表达式语法:以${开头,以}结束,中间为合法的表达式,具体语法格式如下: ${expression} (2)参数说明:Expression:指定要输出的内容,可以是字符串 ...

  9. Linux 基础目录和命令

    Linux 标准目录结构   初学Linux,首先需要弄清Linux 标准目录结构 / root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home --- 存 ...

  10. HDU 1358 Period(KMP计算周期)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1358 题目大意:给你一串字符串,判断字符串的前缀是否由某些字符串多次重复而构成. 也就是,从第1个字母 ...