SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE),但是一般情况下他的复杂度还是很优秀的,为O(mn),其中稀疏图中m约等于2,稠密图...关于SPFA:他死了,n为边数(值得一提,有的非常bt的数据会故意卡spfa不让你过   比如菊花图,蒲公英图什么的)

算法大意:设立一个队列来保存所有待优化的结点,先初始化所有最短路径,然后从起点开始不断遍历每一条边,不断进行松弛操作,再用已经优化完的结点去更新队列中其他节点

重要变量解释:

dis表示从源点到点i的最短路径
vis表示这个点目前是否在队列里
head表示这个点所有出边中序号最大的那一条

代码:

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<time.h>
#include<queue>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-1);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define fi first
#define sc second
ld eps=1e-9;
ll pp=1000000007;
ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;
}
//head const int inf=2147483647;
int n,m,s;//点的个数、有向边的个数、出发点的编号
int dis[10005],vis[10005],head[10005],cnt;
//dis表示从源点到点i的最短路径
//vis表示这个点目前是否在队列里
//head表示这个点所有出边中序号最大的那一条 struct Edge
{int next,dis,to;
}edge[9999999];queue <int> q;inline void add_edge(int from,int to,int dis)
{cnt++;edge[cnt].next=head[from];edge[cnt].to=to;edge[cnt].dis=dis;head[from]=cnt;
}//存边 void spfa()
{rep(i,1,n)dis[i]=inf,vis[i]=0;//初始化 dis[s]=0;vis[s]=1;//把始点标记成在队列中 q.push(s);//入队 while(!q.empty()){int u=q.front();//队首的点 q.pop();//出队 vis[u]=0;//标记成已经出队 for(int i=head[u];i;i=edge[i].next)//遍历每一条边
        {int v=edge[i].to;if(dis[v]>dis[u]+edge[i].dis){dis[v]=dis[u]+edge[i].dis;//松弛操作 if(!vis[v]){q.push(v);vis[v]=1;}//入队
            }}}
}int main()
{scanf("%d %d %d",&n,&m,&s);for(int i=1;i<=m;++i){int u,v,d;//第i条有向边的出发点、目标点和长度scanf("%d %d %d",&u,&v,&d);add_edge(u,v,d);}spfa();for(int i=1;i<=n;++i){if(i==s) printf("0 ");//自己到自己为0 else printf("%d ",dis[i]);}return 0;
}

感觉和Dijkstra差不多,但其实他俩区别还是很大的

Dijkstra是找到从当前节点所有出边中找到最短的,然后用这条最短边继续更新其他路径

而SPFA是对当前节点的所有出边不断进行松弛操作,然后用更新完的边去更新其他结点的其他边

(其实好像挺像的)

转载于:https://www.cnblogs.com/lcezych/p/10759139.html

SPFA求最短路——Bellman-Ford算法的优化相关推荐

  1. c语言bellman算法,求 最短路径中BELLMAN FORD算法实现的C程序

    匿名用户 1级 2010-06-01 回答 //这个是邻接表 typedef struct oo { int len,num; struct oo *next; } link; typedef str ...

  2. bellman ford 算法 判断是否存在负环

    Flyer 目录视图 摘要视图 订阅 微信小程序实战项目--点餐系统        程序员11月书讯,评论得书啦        Get IT技能知识库,50个领域一键直达 关闭 bellman for ...

  3. Bellman Ford算法详解

    一.用途 1. Bellman Ford算法是解决拥有负权边最短路问题的方法之一.还有一种方法是SPFA算法. 2. 二者相比,SPFA算法在效率方面是优于Bellman Ford算法的.但在某些情况 ...

  4. bellman - ford算法c++

    (最短路III)bellman - ford算法(适用于含负权边的图) 注意:用该算法求最短路,在有边数限制的情况下可以存在负权回路!且对所走的边的数量有要求时只能用该算法实现! 解析:因为如果没有边 ...

  5. Bellman ford算法(贝尔曼·福特算法)

    Bellman - ford算法是求含负权图的单源最短路径的一种算法,效率较低,代码难度较小.其原理为连续进行松弛,在每次松弛时把每条边都更新一下,若在n-1次松弛后还能更新,则说明图中有负环,因此无 ...

  6. Bellman——Ford算法

    Bellman--Ford 算法介绍 思路讲解 案例分析与代码实现 案例分析 代码实现 优先队列优化(SPFA) 优化原理 代码实现 算法介绍 我们知道Dijkstra算法只能用来解决正权图的单源最短 ...

  7. AcWing 851. spfa求最短路(解决负边权最短路)

    题目链接 https://www.acwing.com/problem/content/853/ 思路 就是SPFA求最短路的模板,其思路大概是我们要更新所有能被松弛的边,然后更新松弛的边的边,然后就 ...

  8. LeetCode 787. K 站中转内最便宜的航班(图/Bellman Ford算法)

    文章目录 贝尔曼-福特算法(Bellman-Ford) 简介 算法思想 算法执行过程 应用 题目描述 分析 代码 LeetCode 787. K 站中转内最便宜的航班 题目描述 Bellman For ...

  9. 图解Bellman Ford算法

    Bellman Ford 单源最短路径算法[中字] Bellman Ford 单源最短路径算法[中字]_哔哩哔哩_bilibili 贝尔曼-福特算法(Bellman–Ford algorithm )油 ...

  10. 851. spfa求最短路 Java题解 (spfa)

    输入样例: 3 3 1 2 5 2 3 -3 1 3 4 输出样例: 2 算法思路: spfa最短路算法是对bellmanFord算法的优化,用于求单源最短路间的带负权的算法,一般时间复杂度为O(m) ...

最新文章

  1. [图示]营销理论:不同时代的用户如何接受一个新事物?
  2. Android --- 很好用的时间选择器
  3. log4j 禁止类输出日志_log4j 2过滤spring日志遇到的问题
  4. Android mock for循环,Android单元测试(五):依赖注入,将mock方便的用起来
  5. 信息学奥赛一本通C++语言——1119:矩阵交换行
  6. Hadoop2.6.0中YARN底层状态机实现分析
  7. 【06年博文搬家】一个修改时间的批处理程序
  8. python-线程互斥锁与递归锁
  9. Unity3d 好友管理系统
  10. Java校招基础知识总结(横扫BAT,就业经验交流会演讲稿)
  11. MySQL专题系统归纳快速上手(常用cmd命令,常用函数汇总,SQL语句精讲带示例)适用初学、用法速查
  12. KubeEdge 王泽锋:只有代码没有生命力,凝聚开发者的社区才能活力无限 I OpenTEKr 大话开源 Vol.8
  13. 三元运算符(三目运算符)
  14. 零基础 Python学习
  15. POND:高效的 Python 通用对象池库
  16. 2005年的网易邮箱长什么样的?
  17. C++11 新特性。
  18. SpringBoot整合微信支付开发在线教育视频网站(完整版)
  19. Android webview 自动登陆新浪微博实现(原理)
  20. AE开发笔记(二)制图输出

热门文章

  1. 我的世界java导出皮肤_我的世界Alex1.8夕立poi皮肤
  2. IDEA debug模式,修改集合的值
  3. RestTemplate的基本使用
  4. eclipse 自定义文档注释的作者
  5. Git如何忽略已经上传的文件或文件夹?
  6. Android开发笔记(一百一十五)设计工具
  7. Debian 项目领导人职位已有三位侯选者
  8. HTML5的 2D SVG和SVG DOM的学习笔记(2)---SVG动画
  9. Python之网络编程(Socket)
  10. 标量、向量、矩阵、张量