SPFA + 静态邻接表 模板

  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 ;
}

 

 

 

你可能感兴趣的:(SPFA)