单源最短路-SPFA版本 学习笔记

关于SPFA

它死了。

NOI2018第一题 归程,很多选手使用了一种广为人知一种求最短路的算法——SPFA,最后,由于SPFA算法被造数据的人卡掉了,结果:
10060
AgCu
希望大家不要重蹈覆辙。

这一题的正解是Dijstra,但是,我们先讲讲SPAFA,毕竟是我还是一个普及组的蒟蒻,而普及组不会被卡SPFA。
关于Dijstra的题解可以点击这里

算法实质

关于SPFA,其实就是一个松弛计划。说白了,就是这样的:

2
4
3
1
2
3

首先令disti为第i个点到1号点的最短路,那么,dist1=0
接下来我们遍历这张图(这里用dfs,但代码一般是用bfs更快)。
先遍历2号点,那么dist2=2。然后继续dist3=6就可以了。
接下来是重点我们回到3号点这是3号点已经有值了,但是原来的dist3的值是6,但是,我们遍历过来的时候的值为3(dist1+3),比原来的dist3小,这是我们就可以把dist3=3就可以了,这样这张图的遍历就完成了。

算法缺点

如果出题人有意造数据,你遍历了这张图,先从第一个点开始遍历,然后遍历完这张图,把所有的点都得到了一个值,然后回来发现,这个值都是加的,这样就会浪费掉大量的时间,就会被卡成O(N×M)的复杂度了,接下来就是TLE了,所以,这里建议使用广度优先搜索。

代码实现

这里用链式前向星来存图以及BFS。
关于BFS

#include<cstdio>//SPAFA
#include<queue>//采用链式前向星
#include<cstring>//BFS
#define maxn 500039
using namespace std;
int to[maxn],nex[maxn],head[maxn],q[maxn],k;
int n,m,i,f,t,s,qq;
int ans[maxn];
void add(int x,int y,int z){
to[k]=y; q[k]=z;
nex[k]=head[x];
head[x]=k;
k++;
return;
}
void bfs(int x){
queue<int> qq;
int now; ans[x]=0;
qq.push(x);
while(!qq.empty()){
int cur=qq.front(); qq.pop();
for(int i=head[cur];i!=-1;i=nex[i]){
if( ans[cur] + q[i] >= ans[to[i]] )
continue;
ans[to[i]] = ans[cur] + q[i];
qq.push(to[i]);
}
}
return;
}
int main(){
scanf("%d%d%d",&m,&n,&s);
memset(ans,0x3f,sizeof(ans));
memset(head,-1,sizeof(head));
memset(nex,-1,sizeof(nex));
ans[s]=0;
for(i=1;i<=n;i++){
scanf("%d%d%d",&f,&t,&qq);
add(f,t,qq);
}
bfs(s);
for(int i=1;i<=m;i++)
if(ans[i]==0x3f3f3f3f)
printf("2147483647 ");
else printf("%d ",ans[i]);
return 0;
}
posted @   jiangtaizhe001  阅读(56)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示