最短路径SPFA算法

本文介绍了SPFA算法,一种用于求解无向图最短路径的优化方法,基于队列操作,时间复杂度为O(KM),适用于有负边权的情况。文章详细阐述了算法步骤和注意事项,包括与Dijkstra算法的区别和适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

如果你对图论相关知识一点也没有,那么建议您先去了解这些知识:
讲解视频1
讲解视频2
画图工具


算法思想

队列优化,去掉一些无用的松弛操作,用队列来维护松弛造作的点。继承了Bellman-Ford算法的思想,但时间复杂度相对来说提高了很多。

与BFS的算法有一些类似,利用了STL队列。


时间复杂度

理想复杂度为O ( K M ) O(KM)O(KM),这里的K KK可以看作一个常数

最坏为O ( N M ) O(NM)O(NM)但是一般情况下是跑不到这么多(除非出题人卡SPFA)



注意

虽然大多数情况spfa跑的比较快,但时间复杂度仍为(Onm),主要用应用于有负边权的情况(如果没有负边权,推荐使用 Dijkstra算法)。利用了邻接表建图,数据结构的基础一定要掌握好,而且该算法很容易超时,被卡,必须要谨慎选择该算法。


算法分析

1.用dis数组记录点到有向图的任意一点距离,初始化起点距离为0,其余点均为INF,起点入队。

2.判断该点是否存在。(未存在就入队,标记)

3.队首出队,并将该点标记为没有访问过,方便下次入队。

4.遍历以对首为起点的有向边(t,i),如果dis[i]>dis[t]+w(t,i),则更新dis[i]。

5.如果i不在队列中,则入队标记,一直到循环为空。


例题(模板)

题目:求一个无向图的最短路径(dijkstra)

题目描述

一个含n个结点的无向图,以矩阵存储方式给出,请求出指定的两个点之间的最短距离。

输入输出格式

输入格式:

第一行,一个整数n(0 < n < 1000 ),表示无向图中结点的个数。
  接下来是一个n*n的矩阵,表示无向图中各结点之间的联结情况,矩阵中的数值为小于等于1000的下整数,其中 0 表示两点之间无直接连接。
  最后一行,两个整数i,j。表示求解i点到j点的最短距离。

输出格式:

一个数值,表示指定的两点之间最短距离。

输入输出样例

输入样例:
2
0 2
2 0
1 2
输出样例:
2

Code

#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,x,y,s,t,i,j,a[1100][1100],b[1100],c[1100];
int main()
{
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
		{
			scanf("%lld",&a[i][j]);
			if(!a[i][j])
				a[i][j]=10000;
		}
	scanf("%lld%lld",&x,&y);
	c[x]=1;
	for(i=1;i<=n;i++)
		b[i]=a[x][i];
	for(i=1;i<=n;i++)
	{
		s=1;
		t=10000;
		for(j=1;j<=n;j++)
			if(!c[j]&&t>b[j])
			{
				s=j;
				t=b[j];
			}
		c[s]=1;
		for(j=1;j<=n;j++)
			if(!c[j]&&b[s]+a[s][j]<b[j])
				b[j]=b[s]+a[s][j];
	}
	printf("%lld",b[y]);
	return 0;
}


以上就是本文的内容,请在评论区提出您宝贵的意见,谢谢!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值