spfa
转载请注明出处HTTPs://blog.csdn.net/bestsort
个人感觉看SPFA之前推荐先看最短路 dijkstra 算法详解与模板
因为只有脑中理解了Dijkstra的寻路过程,相互印证下,才能更好的理解SPFA
SPFA核心思想:如果一个点上次没有被松弛过,那么下次就不会从这个点开始松弛。每次把被松弛过的点加入到队列中,就可以忽略掉没有被松弛过的点
而且SPFA相比dijkstra算法还有个优势:可以处理负权图和判负环,判负环只需要再加一个if和统计入队次数的num数组即可(注释部分)
每一行代码的含义都在代码注释里了
附一道例题:HDU2544
最短路
Time limit: 5000/1000 MS (java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 83934 Accepted Submission(s): 36317
Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
2 11 2 33 31 2 52 3 53 1 20 0
Sample Output
32
#include <iOStream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#define For(a,b) for(int a=0;a<b;a++)
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f; //无穷大
const int inf = 0x3f;
const double PI = acos(-1);
struct edge {
int e,w;
edge(int _e,int _w) { //构造函数,使用edge(a,b) 可以直接构造一个e = a,w = b结构体
e = _e,w = _w;
}
//如果需要申请结构体变量,还需要加上下面这个构造函数
//edge(){};(对没错里面都是空的)
};
vector<edge> Map[maxn]; //邻接表存图
bool vis[maxn]; //该点是否在队列中
int dis[maxn]; //初始点到每点的最短距离
int n,m;
void spfa(int a) {
memset(dis,inf,(n+1)<<2); //将数组中前n+1个数初始化为无穷大
mem(vis,0);
dis[a] = 0;
vis[a] = true;
/*****************上面都是和Dijkstra一样的,接下来才是重头******************/
/**Dijkstra:每次找权值最小的边,然后根据这个边所连的点更新dis数组
所以每n次操作只能找出一个点来
SPFA:如果该边可以松弛且连接的点未被使用,就把该边连接的那个点存进队列等待更新
所以每经过一个点就可以把该点所有边所连接的点(可以被松弛的)都记录然后更新
*/
queue<int>q;
q.push(a);
while(!q.empty()) {
int buf = q.front(); //取出队首的点
q.pop();
vis[buf] = 0;
For(i,Map[buf].size()) {
int p = Map[buf][i].e; //取出队首的点
int w = Map[buf][i].w;
if(dis[buf]+w < dis[p]) { //如果可以松弛就更新dis数组,此处和Dijkstra一样
dis[p] = dis[buf]+w; //松弛的同时如果该点未被访问就把该点扔进队列
if(!vis[p]) { //不同的地方,如果p点未被使用,则将其放入队列(也就是p点可以被松弛)
//num[p]++;
//if(num[p]>n+1)
//return false;
q.push(p);
vis[p] = 1;
}
}
}
}
//return true;
}
int main() {
int p1,p2,w;
while(cin >> n >> m) {
if(!n&&!m)
break;
For(i,n)
Map[i].clear();
For(i,m) {
cin >> p1 >> p2 >> w;
//构建无向图
Map[p1].push_back(edge(p2,w));
Map[p2].push_back(edge(p1,w));
}
spfa(1);
cout << dis[n] <<endl;
}
return 0;
}
相关阅读
该文档是产品项目由“概念化”阶段进入到“图纸化”阶段的最主要的一个文档,其作用就是“对MRD中的内容进行指标化和技术化”,这个
这次我和大家分享一下如何用小程序做一个问卷调查小程序,可以是行业问卷,或者是测试题的。该问卷调查主要介绍题目多且题型多,题目
Axure RP文件下载 | BS后台系统框架模板(源文件下载)
也许很多原型制作的人员都有这种经历,在原型搭建伊始,要花好些时间去构思原型的总体布局怎样比较合理,特别是针对新手而言。这种行为
哈,前一阵子一个比较要好的朋友过生日,就给她做了一个网站作为生日祝福。也花了挺多的时间去复习了抛弃了有一段时间的HTML和CSS,
Bone CollectorTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s)