最短路径--spfa
最短路径----spfa
单源最短路径
思路:
spfa算法是bellman_ford的队列优化算法,bellman是枚举所有的边,所以其时间复杂度为O(nm),而spfa则是只枚举之前改变了值的边,如果当前点被改变了值,则讲这个点放到队列当中去,如果已经在队列当中了,就不需要再次放入队列当中,然后每次取出队列头部的点,再反复操作,整个图没有点被更新,也就是队列为空的时候。
时间复杂度O(km)(k为常数 m为边数)
Code:
#include<iostream>
#include<queue>
#include<memory.h>
#include<cmath>
using namespace std;
const int N=500005;
int head[N],ver[N],edge[N],ne[N];//邻接表存图
int tot,d[N],v[N];
int n,m,s;
void add(int x,int y,int z)
{
ver[++tot]=y;//存放终点
edge[tot]=z;//存放权值
ne[tot]=head[x];//存放下一个点
head[x]=tot;//存放起始点
}
queue<int> q;//定义队列
void spfa(int s)
{
q.push(s);//将起点放入队列
d[s]=0;//初始化起点的值
v[s]=1;//标记起点
while(q.size())//队列里面不为空,如果为空,则证明已经遍历整张图的所有边已经是最短的了
{
int x=q.front();//取出队列中的点 就是上一次更新的最小点
q.pop();//释放刚刚取出的点
v[x]=0;//取消不在队列的点
for(int i=head[x];i;i=ne[i])//遍历整张图
{
int y=ver[i];//y为终点
int w=edge[i];//w为权值
if(d[y]>d[x]+w)//如果起点到y的距离大于起点到x的最短距离加上x到y的距离,则更新起点到y点的距离
{
d[y]=d[x]+w;//更新起点到y点的距离
if(!v[y])//如果y点已经入队 则跳过
{
q.push(y);//将y点入队
v[y]=1;
}
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);//邻接表存图
}
for(int i=1;i<=n;i++)
{
d[i]=pow(2,31)-1;//初始化所有数组d
}
memset(v,0,sizeof(v));//初始化数组v
d[s]=0;//起点到本身的距离为0
spfa(s);//调用spfa
for(int i=1;i<=n;i++)
cout<<d[i]<<' ';//依次输出到各个点的最短路径
return 0;
}

