spfa算法(优化版)

解决问题的范围:存在负边权的最短路问题

时间复杂度:O(km)  m是边的条数k是常数,算法是效率还算是比较高的,这个算法的时间复杂度的最坏是O(n*m)因此当没有负权的时候还是用dijkstra吧

它和dijkstra 的不同点在于spfa 的标记数组是标记是否还在队列中(注意这个)

算法的过程:

加入初始的点,一般都是1,放入队列中,取队列的队首元素,遍历与队首元素相邻的点,如果距离变短则更新这个最短的值,如果这个点不在队列中就加入队列,如果在队列中就不用处理

 

代码中由注释:

 

给出一个模板题:

https://ac.nowcoder.com/acm/problem/14369

code:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f

using namespace std;

const int N=2e5+10;
int head[N],w[N],e[N],ne[N]; 
int dis[N],st[N];//dis 记录每个点到1最短距离   st记录每个点是否在队列中 
int n,m,cnt;

void add(int u,int v,int val){//链式前向星加边 
	e[cnt]=v,w[cnt]=val,ne[cnt]=head[u],head[u]=cnt++;
}

void spfa()
{
	memset(dis,INF,sizeof(dis));
	queue<int> q;
	q.push(1); 
	dis[1]=0;
	st[1]=1; 
	while(q.size()){
		int t=q.front();
		q.pop();
		st[t]=0;//出队置为0 
		for(int i=head[t];i!=-1;i=ne[i]){
			int v=e[i];
			if(dis[v]>dis[t]+w[i]){//更新最短的路径长度,如果该点在队列中就不用操作,不在队列需要加队列中 
				dis[v]=dis[t]+w[i];
				if(!st[v]){
					st[v]=1;
					q.push(v);
				}
			}
		}
	}

}
int main()
{
	memset(head,-1,sizeof(head));
	cin>>n>>m;
	int u,v,val;
	while(m--){
		cin>>u>>v>>val;
		add(u,v,val);
	}
	spfa();
	for(int i=2;i<=n;i++){
		cout<<dis[i]<<endl;
	}
	
	
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值