新学的spfa算法,
spfa算法,就是利用更新的点来更新其他点。被更新的点,放在队列里面,当做其他点到源点的跳板,看看通过被更新的点是否可以缩短到源点的距离~~
#include <iostream>
#include <queue>
#include <cstdio>
const int size=99999999;
using namespace std;
int n,m;
int map[101][101];
int spfa(int s,int e)
{
int low[101];
bool vis[101];
queue<int> q;
for(int i=1;i<=n;i++)
{
vis[i]=false; //入队列为true,不在队列为false.
low[i]=size;
}
low[s]=0;
vis[s]=true;
q.push(s);
while(!q.empty())
{
int m=q.front();
q.pop();
vis[m]=false;
for(int i=1;i<=n;i++)
{
if(low[i]>low[m]+map[m][i]) // 通过m点来更新其他的点
{
low[i]=low[m]+map[m][i];
if(!vis[i]){ //因为i更新过,可以用来更新其他的点
vis[i]=true; //如果i不在队列里面,加入队列
q.push(i);
}
}
}
}
return low[e];
}
int main()
{
while(cin>>n>>m,m+n)
{
int x,y,z;
int sum;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=size;
for(int i=0;i<m;i++)
{
//cin>>x>>y>>z;
scanf("%d%d%d",&x,&y,&z);
map[x][y]=map[y][x]=z;
}
sum=spfa(1,n);
cout<<sum<<endl;
}
return 0;
}
SPFA算法(Shortest Path Faster Algorithm),也是求解单源最短路径问题的一种算法,用来解决:给定一个加权有向图G和源点s,对于图G中的任意一点v,求从s到v的最短路径。 SPFA算法是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算,他的基本算法和Bellman-Ford一样,并且用如下的方法改进:
1、第二步,不是枚举所有节点,而是通过队列来进行优化 设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
2、同时除了通过判断队列是否为空来结束循环,还可以通过下面的方法:判断有无负环:如果某个点进入队列的次数超过V次则存在负环(SPFA无法处理带负环的图)。
#include <iostream>
#include <queue>
#include <cstdio>
const int size=99999999;
using namespace std;
int n,m;
int map[101][101];
int spfa(int s,int e)
{
int low[101];
int inque[101]; //入队的次数
bool vis[101];
queue<int> q;
memset(inque,0,sizeof(inque));
for(int i=1;i<=n;i++)
{
vis[i]=false; //入队列为true,不在队列为false.
low[i]=size;
}
low[s]=0;
vis[s]=true;
inque[s]++;
q.push(s);
while(!q.empty())
{
int m=q.front();
q.pop();
vis[m]=false;
for(int i=1;i<=n;i++)
{
if(low[i]>low[m]+map[m][i]) // 通过m点来更新其他的点
{
low[i]=low[m]+map[m][i];
if(!vis[i]) { //因为i更新过,可以用来更新其他的点
vis[i]=true; //如果i不在队列里面,加入队列
q.push(i);
inque[i]++;
if(inque[i]<n) continue;
else return -1; //存在负边则输出 -1;
}
}
}
}
return low[e];
}
int main()
{
while(cin>>n>>m,m+n)
{
int x,y,z;
int sum;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=size;
for(int i=0;i<m;i++)
{
//cin>>x>>y>>z;
scanf("%d%d%d",&x,&y,&z);
map[x][y]=map[y][x]=z;
}
sum=spfa(1,n);
cout<<sum<<endl;
}
return 0;
}
参考博客:http://www.cnblogs.com/devtang/archive/2011/08/25/spfa.html