SPFA(Shortest Path Faster Algorithm)(队列优化)算法是求单源最短路径的一种算法,在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,是西南交通大学段凡丁于1994年发表的。
原理是从原点出发,遍历与之相连的顶点,不断更新节点的值,将更新了的结点放进队列中,而且用邻接表来存储图。一般用来解决边较少的稀疏图。期望的时间复杂度:O(ke), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2。
<pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f //定义一个很大的数
queue<int> que;
vector<int> vv[100];
int V_count,L_count; //顶点数和边数
//int book[100][100]; //book[]记录某顶点是否走过
long long V[100]; //V[]记录起点到该顶点走的最小距离
int D[100][100]; //D[][]记录两顶点之间距离
int a,b,d;
int len,T;
int main() //顶点编号从 1 --- V_count 初始点为 1
{
while(cin>>V_count>>L_count && V_count && L_count) //输入顶点数和边数
{
for(int i=0;i<100;i++)
{
vv[i].clear(); //清除 指针移到开头
}
while(!que.empty()) que.pop(); //清空
//memset(book,0,sizeof(book));
V[1] = 0;
for(int i=1;i<=L_count;i++)
{
cin>>a>>b>>d;
vv[a].push_back(b);
vv[b].push_back(a);
D[a][b] = D[b][a] =d;
if(i!=1) V[i] = INF;//
}
que.push(1); //初始点放入
while(!que.empty())
{
T=que.front();
len = vv[T].size();
for(int i=0;i<len;i++)
{
if(V[vv[T][i]] > V[T]+D[T][vv[T][i]])//且这么走更近
{
//if(V[vv[T][i]] > V[T]+D[T][vv[T][i]])
V[vv[T][i]] = V[T]+D[T][vv[T][i]];
que.push(vv[T][i]); //放入队列
//book[T][vv[T][i]]=1; //标记为已走过
}
}
que.pop(); //拿出该点
}
for(int i=1;i<=V_count;i++)
{
cout<<"初始点到"<<i<<"点的距离为:"<<V[i]<<endl;
}
}
return 0;
}<pre name="code" class="cpp">/*
我们发现这种写法,太浪费内存空间,D[100][100]; (D[][]记录两顶点之间距离 )所以可以建立一个结构体,里面两个变量,分别是节点号和距离。将该结构体放入到vector中,
struct Node
{
int id;
int dis;
}
vector<Node> vv;
if(V[vv[T][i].id] > V[T]+vv[T][i].dis)//且这么走更近
{
.......
}
/*
测试数据:
6 9
1 2 7
1 3 9
1 6 14
2 3 10
2 4 10
3 4 11
3 6 2
4 5 5
5 6 9
6 9
1 2 7
1 3 2
1 6 14
2 3 2
2 4 10
3 4 11
3 6 2
4 5 5
5 6 9
*/