SPFA可能会被卡掉,能用dijkstra就别用SPFA,代码较长,但我已尽力做到解释,请耐心看下去,存储为邻接表存储。

  1. #include<bits/stdc++.h>
  2. #define inf 0x3f3f3f3f//(宏定义一个很大的值,例如0x3f3f3f3f等)
  3. using namespace std;
  4. int n,m,cnt;//cnt 计数器(有cnt条边)
  5. struct edge//结构体定义
  6. {
  7. int v,w,nxt;//v 目标点 w 边权 nxt 这条边的上一条边(遍历)
  8. };
  9. edge e[3000010];//存边(边表)
  10. int dis[3001000];//记录起点到第x个点的距离
  11. int h[1001000];//记录第x个点所发出的最后一条边
  12. bool f[1001000];//判断是否在队列内
  13. deque<int> q;//双端队列
  14. void add(int,int,int);
  15. void spfa()//SLF优化
  16. {
  17. for(int i=1;i<=n;++i)
  18. {
  19. dis[i]=inf;
  20. }//初始化,也可以用memset()
  21. dis[1]=0;//起点到自己的距离为0 (该题起点为1)
  22. q.push_back(1);//起点入队
  23. f[1]=1;//标志起点已入队
  24. while(!q.empty())
  25. {
  26. int top=q.front();//取队首元素
  27. q.pop_front();//踢出队列
  28. int w=dis[top];//w 起点的值
  29. f[top]=0;//代表该元素已出队
  30. for(int i=h[top];i;i=e[i].nxt)//邻接表遍历每一条边
  31. {
  32. int v=e[i].v;//目标点
  33. int di=e[i].w;//边权
  34. if(dis[v]>w+di)//松弛操作
  35. {
  36. dis[v]=w+di;//更新起点到点v的值
  37. if(!f[v])//判断是否入队,没入队便入队
  38. {
  39. if(!q.empty()&&dis[v]<dis[q.front()])//如果比队首元素小,从队首入队
  40. {//这里一定要把!q.empty()放在前面,编译时它会从前往后读,如果把它放后面而队列又为空,dis[v]<dis[q.front()]调用时会RE
  41. q.push_front(v);//入队操作
  42. }
  43. else q.push_back(v);//否则从队尾入队
  44. f[v]=1;//标志已入队
  45. }
  46. }
  47. }
  48. }
  49. }
  50. int main()
  51. {
  52. memset(h,0,sizeof h);//数组初始化
  53. memset(f,false,sizeof f);//数组初始化
  54. scanf("%d%d",&n,&m);
  55. for(int a,b,c,i=1;i<=m;++i)
  56. {
  57. scanf("%d%d%d",&a,&b,&c);
  58. add(a,b,c); //加边
  59. add(b,a,c);//加边,如果是有向图,删掉这一步操作
  60. }
  61. spfa();//调用函数
  62. printf("%d",dis[n]);//输出,根据题目要求,这里是输出1到n的最短距离
  63. return 0;
  64. }
  65. void add(int u,int v,int w)
  66. {
  67. e[++cnt].v=v;//cnt 边的编号
  68. e[cnt].w=w;
  69. e[cnt].nxt=h[u];//指向上一条边
  70. h[u]=cnt;//更新最后一条边
  71. }

2022.7.8更新:

新增判断负环的写法和dfs写法

dfs写法判断负环更快,但求答案很慢

bfs队列写法求答案快,但判断负环很慢

根据题目情况来

bfs队列写法:

  1. bool spfa()
  2. {
  3. for(rint i=1;i<=n;++i)
  4. dis[i]=0x7ffffff;
  5. dis[0]=0;
  6. q.push_back(0);
  7. vis[0]=true;
  8. ++in[0];//差记录入队次数
  9. while(!q.empty())
  10. {
  11. int u=q.front();
  12. q.pop_front();
  13. vis[u]=false;
  14. for(rint i=h[u];i;i=e[i].nxt)
  15. {
  16. int v=e[i].v;ll w=e[i].w;
  17. if(dis[v]>dis[u]+w)
  18. {
  19. dis[v]=dis[u]+w;
  20. if(!vis[v])
  21. {
  22. ++in[v];
  23. if(in[v]>=n+1) return false;//判断负环
  24. if(!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v);
  25. else q.push_back(v);
  26. vis[v]=true;
  27. }
  28. }
  29. }
  30. }
  31. return true;
  32. }

dfs写法:

  1. void dfs_spfa(int u)
  2. {
  3. if(fg) return;
  4. vis[u]=true;
  5. for(rint i=h[u];i;i=e[i].nxt)
  6. {
  7. int v=e[i].v;
  8. ll w=e[i].w;
  9. if(dis[v]>dis[u]+w)
  10. {
  11. dis[v]=dis[u]+w;
  12. if(vis[v]==true)//如果这个点被访问过,就说明这是负环
  13. {
  14. fg=true;//打标记
  15. return;
  16. }
  17. else dfs_spfa(v);
  18. }
  19. }
  20. vis[u]=false;
  21. }

SPFA算法(SLF优化)2022.7.8更新的更多相关文章

  1. 关于SPFA算法的优化方式

    关于SPFA算法的优化方式 这篇随笔讲解信息学奥林匹克竞赛中图论部分的求最短路算法SPFA的两种优化方式.学习这两种优化算法需要有SPFA朴素算法的学习经验.在本随笔中SPFA朴素算法的相关知识将不予 ...

  2. spfa的SLF优化

    spfa的SLF优化就是small label first 优化,当加入一个新点v的时候如果此时的dis[v]比队首dis[q.front()]还要小的话,就把v点加入到队首,否则把他加入到队尾,因为 ...

  3. HDU4725(KB4-P SPFA+LLL+SLF优化)

    The Shortest Path in Nya Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  4. 并不对劲的图论专题(三):SPFA算法的优化

    1.bzoj1489-> 这是个新套路. 我们希望找到最小的x,那么可以二分x,然后判断是否存在圈的边权的平均值小于等于x. 设圈的边权依次为w1,w2,w3,…,wk,平均值为p, 则有p= ...

  5. 《SPFA算法的优化及应用》——姜碧野(学习笔记)

    一.核心性质:三角不等式.最短路满足d[v]<=d[u]+w(u,v) 二.SPFA两种实现: 常见的是基于bfs的,这是直接对bellman-ford用队列维护.根据最短路的长度最长为(n-1 ...

  6. 蓝书3.3 SPFA算法的优化

    T1 最小圈 bzoj 1486 题目大意: 一个环的权值平均值为定义为一个这个环上所有边的权值和除以边数 求最小的环的权值平均值 思路: 二分一个值 把所有边减去这个值 判断是否有负环 #inclu ...

  7. 队列优化dijsktra(SPFA)的玄学优化

    转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2​ 优化 对一些数 ...

  8. SPFA算法的SLF优化 ——loj#10081. 「一本通 3.2 练习 7」道路和航线

    今天做到一道最短路的题,原题https://loj.ac/problem/10081 题目大意为给一张有n个顶点的图,点与点之间有m1条道路,m2条航线,道路是双向的,且权值非负,而航线是单向的,权值 ...

  9. SPFA求最短路——Bellman-Ford算法的优化

    SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环.SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE), ...

随机推荐

  1. 北航内核操作系统-lab0

    1.lab0环境介绍. 2.进入实验界面. 3.进入实战测试. 任务要求: 3.1编写斐波那契数列. 3.2编写Makefile脚本. Makefile介绍: make命令执行时,需要一个 Makef ...

  2. Spring配置及依赖注入

    入门 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-we ...

  3. Next.js 在 Serverless 中从踩坑到破茧重生

    作者 杨苏博,偏后端的全栈开发,目前负责腾云扣钉的 Cloud Studio 产品.在团队中负责接技术架构设计与 Review.Cloud Studio 编辑器内核设计与开发.部分核心插件设计与开发: ...

  4. 论文阅读 DyREP:Learning Representations Over Dynamic Graphs

    5 DyREP:Learning Representations Over Dynamic Graphs link:https://scholar.google.com/scholar_url?url ...

  5. 运维:ITSM

    IT服务管理(ITSM)是一套帮助企业对IT系统的规划.研发.实施和运营进行有效管理的方法,是一套方法论.ITSM起源于ITIL(IT Infrastructure Library,IT基础架构标准库 ...

  6. 992. Sort Array By Parity II - LeetCode

    Question 992. Sort Array By Parity II Solution 题目大意:给一个int数组,一半是奇数一半是偶数,分别对偶数数和奇数数排序并要求这个数本身是偶数要放在偶数 ...

  7. 【系统问题】windows10打印就蓝屏-报错误代码“win32kfull.sys”

    现象描述: 打印机一打印电脑就蓝屏,蓝屏错误代码为:win32kfull.sys 原因分析: 2021年3月9日-推送了KB5000802补丁更新(操作系统内部版本19041.867和19042.86 ...

  8. MongoDB 各项命名规范

    每日一句 Progress is the result of a bunch of failures. 进步是不断失败的成果. 概述 MongoDB涉及到的一些比如集合啥的命令规范. 集合的命名规范 ...

  9. TornadoFx设置保存功能((config和preference使用))

    原文地址:TornadoFx设置保存功能(config和preference使用) 相信大部分的桌面软件都是存在一个设置的界面,允许用户进行设置的修改,此修改之后需要保存的本地,若是让开发者自己实现, ...

  10. JS - 使用 html2canvas 将页面转PDF

    JS - 使用 html2canvas 将页面转PDF 本方法可以将页面元素块转为pdf. 网站地址 jspdf.js 官网地址:http://jspdf.com GitHub 主页:https:// ...