【算法赌场】SPFA算法

1.算法简介

SPFA 算法的全称是:Shortest Path Faster Algorithm,是西南交通大学 段凡丁 于 1994 年发表的论文中的名字。不过,段凡丁的证明是错误的,且在 Bellman-Ford 算法提出后不久(1957 年)已有队列优化内容,所以国际上不承认 SPFA 算法是段凡丁提出的。

这个事情其实给我们信息学的学习一些启发的。首先,段凡丁肯定是一个大神了,他整理出了这个算法,发表论文。本身,他这篇论文质量很高的,这个算法本身没毛病,问题是作为一个论文,要把一个事情的来龙去脉都说得很清楚很严谨,不仅仅是这段代码能跑成功,而且还要有一个详细的证明过程,证明这段代码运行的结果是正确的,对各种情况进行分析和估算。段凡丁就是在论证这个算法的计算复杂度的时候出现了错误,所以,国际上不怎么承认段凡丁是 SPFA 算法的提出者(逻辑就是你连讲都没讲透彻,这怎么能说就是你的研究成果呢?)。

大家回头想想,如果你学一个算法,要滴水不漏的理解透彻,能讲得出这个算法为什么是对的,是多么呢?人家段大神都在这个问题上栽了大跟斗的。如果你真的要那么做,你一定要找人家的学术论文来看,每一字句去推敲。这个事,就不是我们课堂上那一丁点时间能解决的。所以,从初中开始,大家学习信息学,很多东西就是理解个 7-8 成之后拿来用,你可以有一套自己的思维导图,大致能想明白这个算法为啥是对的,但是,距离严谨证明是有差距的,但能用就行。

2.算法步骤

SPFA 其实是 Bellman-Ford 算法的一个改进。如果仅仅从代码角度来看,两个算法差异很大的,但是,从其思想来看同出一脉。

我们之前说过,Bellman-Ford 算法是有 BFS 算法的影子的,通过 N-1 轮松弛(第一层循环),找到最短路径。因为 N 个顶点的图,最长的简单路径不应该超过 N-1。Bellman-Ford 算法里面的第一层循环就是步数。

既然如此,为了提高效率,我们应该基础每一轮松弛了哪一些点,下一轮,就从这些新点往外延伸去松弛新的点。如果一个点在第 i 轮没有被松弛,我们在第 i-1 轮就不应该试图从它出发去找新的可到达点。这就是 SPFA 算法的核心所在。

为了区分哪一些点是新找到的点,就需要通过一个队列来做控制,新找到的点进队列,一个点往外延伸(类似搜索、探路)了之后,就把他弹出队列。一直重复这个操作,直到队列为空,SPFA 过程就结束了。

cpp 复制代码
struct Edge{ //边的结构体,出发点不需要存,因为边是棣属于顶点的
	int v,w;
}e[500001];

int dis[10001]; 
vector <int> chi[10001];
queue <int> q; 

bool inque[10001];

void SPFA(){
	memset(dis,0x3f,sizeof(dis));
	dis[s] = 0;
	inque[s] = true; // inque 数组是用来记录这个顶点是否在队列当中
	q.push(s);


	while(q.size())
	{
		int u=q.front();
		q.pop();
		inque[u] = false;
		for(int i=0;i<chi[u].size();i++) //从顶点 t 出发,试图松弛一些点
		{
            // chi[u] 是动态数组,存放了从顶点 u 出发的所有边
			Edge tmp_e = e[chi[u][i]];  //chi[u][i] 是边的 id
			int v = tmp_e.v; // 这条边是从 u 到 v
			if(dis[v]>dis[u]+tmp_e.w) //松弛 ee.v 这个顶点,从 s 到 u,再从 u 到 v 是一条更优的路径
			{
				dis[v]=dis[u]+tmp_e.w;
				//v 是新探索到的顶点,放入队列
                if(!vis[v]){
					q.push(v);
					inque[v] = true;
				}
			}
		}
	}
}
相关推荐
thesky123456几秒前
活着就好20241224
学习·算法
ALISHENGYA6 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
guogaocai1238 分钟前
连续自成核退火热分级(SSA)技术表征共聚聚丙烯(PP)分子链结构
算法
DARLING Zero two♡32 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
游是水里的游1 小时前
【算法day19】回溯:分割与子集问题
算法
不想当程序猿_1 小时前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
南城花随雪。2 小时前
单片机:实现FFT快速傅里叶变换算法(附带源码)
单片机·嵌入式硬件·算法
dundunmm2 小时前
机器学习之scikit-learn(简称 sklearn)
python·算法·机器学习·scikit-learn·sklearn·分类算法
古希腊掌管学习的神2 小时前
[机器学习]sklearn入门指南(1)
人工智能·python·算法·机器学习·sklearn
波音彬要多做2 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法