最短路径--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; }