SPFA算法的优点绝不仅限于它优异的时间复杂度,它还可以判负权回路啊!
**定义:**SPFA(Shortest Path Faster Algorithm)(队列优化)算法是求单源最短路径的一种算法,它还有一个重要的功能是判负环(在差分约束系统中会得以体现),在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。
——(引自百度词条)
Bellman-Ford算法:对于每一条边都不加判断地进行一次松弛操作,以得到每一个点到第一个点的最小距离,时间复杂度为O(E)。
SPFA算法:因为Bellman-Ford算法中有很多松弛操作都是多余的,所以我们只要简化它的松弛就可以了,我们发现用没有被松弛操作更新的点不能继续更新其他的点,我们就维护一个队列,用来存储松弛点的序列。
优化:邻接表+队列(最短路算法中稳定且优秀)
/*
2016.8.6 BulaBulaCHN
*/
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
struct Edge
{
int from,to,next;
int val;
}eage[10005];
int n,m;
int head[105];
int tot=0;
int dis[105];
int que[505];
bool book[10005];
int top=0;
int tail=0;
void Insert(int x,int y,int z)
{
eage[++tot].from=x;
eage[tot].to=y;
eage[tot].val=z;
eage[tot].next=head[x];
head[x]=tot;
}
int main()
{
freopen("textdata.in","r",stdin);
freopen("textdata.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Insert(x,y,z);
Insert(y,x,z);
}
for(int i=1;i<=n;i++) dis[i]=999999;
dis[1]=0;
for(int i=head[1];i;i=eage[i].next)
{
if(dis[eage[i].to]>dis[1]+eage[i].val)
{
dis[eage[i].to]=dis[1]+eage[i].val;
if(!book[eage[i].to])
{
que[++tail]=eage[i].to;
book[eage[i].to]=1;
}
}
}
while(top<tail)
{
top++;
for(int i=head[que[top]];i;i=eage[i].next)
{
if(dis[eage[i].to]>dis[que[top]]+eage[i].val)
{
dis[eage[i].to]=dis[que[top]]+eage[i].val;
if(!book[eage[i].to])
{
que[++tail]=eage[i].to;
book[eage[i].to]=1;
}
}
}
}
for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
fclose(stdin);
fclose(stdout);
return 0;
}
/*
textdata.in
4 8
1 2 2
1 3 6
1 4 4
2 3 3
3 1 7
3 4 1
4 1 5
4 3 12
textdata.out
0 2 5 4
*/