SPFA最短路算法

SPFA:Shortest Path Faster Algoriithm 快速最短路径算法

SPFA的核心算法就是Bell-Ford算法。它使用一个队列或者一个栈来减少了Bell-Ford中不必要的松弛。可以处理负边和环的情况,他的使用比Dijstra更广泛。但是未经优化的SPFA算法时间复杂度不稳定,测试用例对它的影响较大。所以有的时候为了简单方便,我们直接使用Dijstra算法来解决。

SPFA实现的过程非常类似于BFS。他们都是使用队列来维护,不同的是,BFS的每个顶点只入队一次,而SPFA的结点则课能会入队多次。所以我们需要一个数组bool vis[] 来记录该顶点是否在队列中。SPFA实现过程如下:

步骤一: 首先将将源点s入队,将所有点到s的距离设置为dis[i]=∞,dis[s]=0

步骤二:如果队列为空,算法终止。否则取出队首元素u,将与u相连的边<u,v>进行松弛,如果dis[u]距离更新了且u不在队列中,则将u入队,若u进队次数大于n(总顶点数),则说明有负环,立即结束算法。

步骤三:不断地重复步骤二,直到算法结束

SPFA算法的时间复杂度取决于顶点总共的入队次数,他的算法时间复杂度为O(ke),e是边数,k是每个节点平均入队的次数,一般有k<2.

#include<queue>
#define INF INT_MAX/2
#define MAX_SIZE 1000
int dis[MAX_SIZE];          //保存最短距离
bool vis[MAX_SIZE];
int a[MAX_SIZE][MAX_SIZE];  //邻接矩阵存储
int times[MAX_SIZE];        //记录顶点入队次数
bool SPFA(int s,int n) {
    int i,v;
    bool label = 1;                  //用来记录是否会出现环
    memset(vis, 0, sizeof(vis));
    memset(times, 0, sizeof(times));
    queue<int>Q;                   //保存顶点的队列
    for (i = 0; i <n; i++)
        dis[i] = INF;       //初始化为无穷
    dis[s] = 0;             //源节点
    Q.push(s);                //源节点入队
    vis[s] = 1;          //源节点在队列中,所以标记为1
    times[s]++;
    while (!Q.empty()){        //如果队列非空
        v = Q.front();         //取出队列一个元素
        Q.pop();
        vis[v] = 0;        //将该点标记为不在队列中
        for (i = 0; i < n; i++) {                   //松弛该点的邻边
            if (dis[i] > a[v][i] + dis[v]) {
                dis[i] = a[v][i] + dis[v];      //松弛一把更新距离
                if (!vis[i]) {         //如果被松弛的顶点i不在队列中
                    vis[i] = 1;        //加入队列并标记
                    Q.push(i);
                    if (times[++i] > n) {   //入队次数加1次,如果入队次数超过n的话,表示有环
                        label = 0;
                        break;
                    }
                }
            }
        }
        if (!label)
            break;
    }
    return label;           //若有环返回0,无环返回1
}
时间: 2024-11-25 06:37:12

SPFA最短路算法的相关文章

hdu 4568 spfa 最短路算法+旅行商问题

http://acm.hdu.edu.cn/showproblem.php?pid=4568 Problem Description One day, a hunter named James went to a mysterious area to find the treasures. James wanted to research the area and brought all treasures that he could. The area can be represented a

【算法】祭奠spfa 最短路算法dijspfa

题目链接 本题解来源 其他链接 卡spfa的数据组 题解堆优化的dijkstra 题解spfa讲解 来自以上题解的图片来自常暗踏阴 使用前向星链表存图 直接用队列优化spfa struct cmp { bool operator()(int a,int b) { return dist[a]>dist[b]; } }; priority_queue<int,vector<int>,cmp> q;void dijspfa() { q.push(s); memset(inq,0,

最短路算法 :Bellman-ford算法 &amp; Dijkstra算法 &amp; floyd算法 &amp; SPFA算法 详解

 本人QQ :2319411771   邮箱 : [email protected] 若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   :http://www.cnblogs.com/Yan-C/p/3916281.html . 很早就想写一下最短路的总结了,但是一直懒,就没有写,这几天又在看最短路,岁没什么长进,但还是加深了点理解. 于是就想写一个大点的总结,要写一个全的. 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并

[ACM] 最短路算法整理(bellman_ford , SPFA , floyed , dijkstra 思想,步骤及模板)

以杭电2544题目为例 最短路 Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路.N=M=0

最短路算法(floyed+Dijkstra+bellman-ford+SPFA)

最短路算法简单模板 一.floyed算法 首先对于floyed算法来说就是最短路径的动态规划解法,时间复杂度为O(n^3) 适用于图中所有点与点之间的最短路径的算法,一般适用于点n较小的情况. Floyed算法有三层循环,循环的层次先后顺序也是比较重要的,分别为k ,i,j:因为dis[k][i][j]代表的是i节点到j节点的最短路如果中间经过节点k的话dis[k][i][j] =dis[k-1][i][k]+dis[k-1][k][j]:否则dis[k][i][j] = dis[k-1][i]

最短路算法汇总

校赛完了,这次校赛,做的很差,一个算法题没有,2个水题,1个贪心,概率DP,DP,数论题.DP还没开始研究,数论根本不会,数学太差了,省赛时卡数论,校赛依然卡数论,我擦,还是得继续学习啊! 一把锈迹斑斑的剑,只有不断的磨砺,才能展露锋芒! 以下为最短路总结: 最短路问题可分为: 一.单源最短路径算法,解决方案:Bellman-Ford算法,Dijkstra算法,SPFA 二.每对顶点间的最短路径算法:Floyd: (1).Dijkstra算法: (经典的算法,可以说是最短路问题的首选事例算法,但

最短路算法大杂烩

最短路算法主要有以下几个: 一 Dijkstra 二 Bellman-Ford 三 SPFA 四 ASP 五 Floyd-Warshall 首先约定一下图的表示: struct Edge{         int from,to,wt;     };     vector<int>G[N];     vector<Edge>G[N]; -------------Dijkstra算法 使用条件:无负权边 复杂度O:((V+E)*log(V)) 下面是用优先队列实现的Dijkstra算

近十年one-to-one最短路算法研究整理【转】

前言:针对单源最短路算法,目前最经典的思路即标号算法,以Dijkstra算法和Bellman-Ford算法为根本演进了各种优化技术和算法.针对复杂网络,传统的优化思路是在数据结构和双向搜索上做文章,或者针对不必要的循环进行排除.近年来,最短路算法大量应用于需要高及时性的领域,比如GIS领域,也大量应用于网络规模巨大的社会网络分析领域,这使得传统思路并不能很好地解决,于是把最短路算法思路本身抽象成两阶段算法,第一阶段为数据预处理,第二阶段为实时地搜索.这二者是互相矛盾的,如何找到平衡是各种算法技术

vijos1635 SPFA和FLOYD算法如何打印路径

之前打的spfa或是floyd都只是用来求最短路,对于如何打印路径问题一点都没有概念 可能也是因为对于原理没有很理解的缘故? 总之,之后赶紧看了一下,现在总算是明白了.....MARK一下自己的理解 早晨碰到了一题挺裸的最短路问题:vijos1635 1.首先说说spfa的方法: 其实自己之前打的最多的spfa是在网格上的那种,也就是二维的 一维的需要邻接表+queue 以及对于queue的操作,自己也是醉了 这里贴一个模板(不含打印路径): #include<cstdio> #include