SPFA算法模板

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
*/ 


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值