SPFA — shotest path faster algorithm,是一个效率很高的求最短路径的算法,也可以说是bellman-ford算法的优化版。
具体做法是先把起点放入一个队列中。每次取出队顶元素,并pop,看跟该点相邻的其他点是否能够松弛,如果可以松弛,改变数值,如果该点不在队列中,则把能该点push到队列中,直到队列为空。
为了速度更快,可以用邻接表来存储,这样,找与起点相邻的点的速度就会很快!
若要判负环路,则记录一个点的入队次数,若超过边数,则有负权环。
自己用SPFA+静态邻接表写的hdu_2544:可以用作模板(实际上只要理解了是不需要模板的)
代码
#include <iostream>
#include <queue>
using namespace std;
const long lmax = 1000000000;
const long edge_maxn = 10005; //边的最大上限
const long point_maxn = 105; //点的最大上限
struct node
{/*node存储边,一个edge代表一条边*/
int v; //终点位置
int w; //权值
int next; //同一起点的下一条边存储在edge数组中的位置(理解了这个静态邻接表就可以了)
}edge[edge_maxn];
int pre[point_maxn]; //以该点为起点的第一条边存储在edge数组中的位置
int n; //点的数量
int m; //边的数量
queue<int> Q;
int dirs[point_maxn];
bool vis[point_maxn];
void Init()
{
memset(pre,-1,sizeof(pre));
int Index = 1;
int i,j,flag;
int x,y,w;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
for(flag=0,j=pre[x];j!=-1;j=edge[j].next)
{//重边的情况
if(y == edge[j].v)
{
if(w < edge[j].w)
edge[j].w = w;
flag = 1;
break;
}
}
if(flag == 1)
continue;
edge[Index].v = y;
edge[Index].w = w;
edge[Index].next = pre[x]; //保存x起点的上一条边在edge数组中的位置
pre[x] = Index++; //位置更新
swap(x,y);
edge[Index].v = y;
edge[Index].w = w;
edge[Index].next = pre[x];
pre[x] = Index++;
}
}
void print(int end)
{
printf("%d\n",dirs[end]);
}
void SPFA()
{
int start = 1;
int end = n;
while(!Q.empty())
{
Q.pop();
}
memset(vis,0,sizeof(vis));
fill(dirs,dirs+point_maxn,lmax);
dirs[start] = 0;
vis[start] = 1;
Q.push(start);
while(!Q.empty())
{
int top = Q.front(); //边的起点
Q.pop();
vis[top] = 0;
for(int j=pre[top];j!=-1;j=edge[j].next)
{
int e = edge[j].v; //边的终点
if(dirs[e] > edge[j].w + dirs[top])
{
dirs[e] = edge[j].w + dirs[top];
if(!vis[e])
{
Q.push(e);
vis[e] = 1;
}
}
}
}
print(end);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0))
{
Init();
SPFA();
}
//system("pause");
return 0;
}