SPFA求最短路——Bellman-Ford算法的优化
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(-);
#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-;
ll pp=;
ll mo(ll a,ll pp){if(a>= && a<pp)return a;a%=pp;if(a<)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=;for(;b;b>>=,a=mo(a*a,pp))if(b&)ans=mo(ans*a,pp);return ans;}
ll read(){
ll ans=;
char last=' ',ch=getchar();
while(ch<'' || ch>'')last=ch,ch=getchar();
while(ch>='' && ch<='')ans=ans*+ch-'',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
//head const int inf=;
int n,m,s;//点的个数、有向边的个数、出发点的编号
int dis[],vis[],head[],cnt;
//dis表示从源点到点i的最短路径
//vis表示这个点目前是否在队列里
//head表示这个点所有出边中序号最大的那一条 struct Edge
{
int next,dis,to;
}edge[]; 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,,n)
dis[i]=inf,vis[i]=;//初始化
dis[s]=;
vis[s]=;//把始点标记成在队列中
q.push(s);//入队
while(!q.empty())
{
int u=q.front();//队首的点
q.pop();//出队
vis[u]=;//标记成已经出队
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]=;
}//入队
}
}
}
} int main()
{
scanf("%d %d %d",&n,&m,&s);
for(int i=;i<=m;++i)
{
int u,v,d;//第i条有向边的出发点、目标点和长度
scanf("%d %d %d",&u,&v,&d);
add_edge(u,v,d);
}
spfa();
for(int i=;i<=n;++i)
{
if(i==s) printf("0 ");//自己到自己为0
else printf("%d ",dis[i]);
}
return ;
}
感觉和Dijkstra差不多,但其实他俩区别还是很大的
Dijkstra是找到从当前节点所有出边中找到最短的,然后用这条最短边继续更新其他路径
而SPFA是对当前节点的所有出边不断进行松弛操作,然后用更新完的边去更新其他结点的其他边
(其实好像挺像的)
SPFA求最短路——Bellman-Ford算法的优化的更多相关文章
- 基于bellman-ford算法使用队列优化的spfa求最短路O(m),最坏O(n*m)
acwing851-spfa求最短路 #include<iostream> #include<cstring> #include<algorithm> #inclu ...
- ACM - 最短路 - AcWing 851 spfa求最短路
AcWing 851 spfa求最短路 题解 以此题为例介绍一下图论中的最短路算法 \(Bellman\)-\(Ford\) 算法.算法的步骤和正确性证明参考文章最短路径(Bellman-Ford算法 ...
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- spfa求次短路
思路:先算出每个点到1的最短路d1[i],记录下路径,然后枚举最短路上的边 删掉之后再求一遍最短路,那么这时的最短路就可能是答案. 但是这个做法是错误的,可以被卡掉. 比如根据下面的例题生成的一个数据 ...
- 851. spfa求最短路(spfa算法模板)
给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible. 数据保证不存在负权回路. 输入格式 ...
- Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】
题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...
- Holy Grail【spfa求最短路】
题目链接:https://www.jisuanke.com/contest/3004?view=challenges 题目大意: 1.一个无向图,给出六个顶点,添六条边,但是添边是有限制的.每次添边的 ...
- 851. spfa求最短路
给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible. 数据保证不存在负权回路. 输入格式 ...
随机推荐
- 如何探测网络设备ACL规则
探测网络设备ACL规则 背景:在互联网企业的生产网络中,往往在网络入口处的网络设备上会有成千上万条ACL策略,这么多的ACL导致了网络管理员很难彻底梳理清楚其中的逻辑关系,从而不知道到底对外开放了哪些 ...
- SpringBoot系列——jar包与war包的部署
前言 Spring Boot支持传统部署和更现代的部署形式.jar跟war都支持,这里参考springboot参考手册学习记录 两种方式 jar springboot项目支持创建可执行Jar,参考手册 ...
- K2制作流程
K2流程制作注意事项 1:分析需求 2:实施 步骤1:绘制流程图 步骤2:添加datafield[必备:ActJumped IsPass] 步骤3:添加线规则(如下图所示,在添加完毕规则之后,再给同 ...
- C# 连接/查询Jira
查询jira数据,如果是前端,可以按照如下格式直接访问,获取数据 http://jira.company.com/rest/api/2/search?jql=project = REM AND res ...
- @Data注解使用后在eclipse中get/set报错解决方法
Maven项目中已经导入相关的lombok.jar包但是使用后仍提示无set/get方法 安装完成之后,请确认eclipse安装路径下是否多了一个lombok.jar包,并且其 配置文件eclipse ...
- JavaScript学习之自动轮播图片
定时器 在实现轮播图之前需要首先了解一下JavaScript的定时器 setInterval()和clearInterval() 1.setInterval() 方法可按照指定的周期(以毫秒计)来调用 ...
- (最完美)MIUI12系统的Usb调试模式在哪里开启的步骤
当我们使用安卓手机通过数据线链接到Pc的时候,或者使用的有些app比如我们公司营销小组当使用的app引号精灵,之前的老版本就需要开启usb调试模式下使用,现当新版本不需要了,如果手机没有开启usb调试 ...
- 智能指针std::unique_ptr
std::unique_ptr 1.特性 1) 任意时刻只能由一个unique_ptr指向某个对象,指针销毁时,指向的对象也会被删除(通过内置删除器,通过调用析构函数实现删除对象) 2)禁止拷贝和赋值 ...
- RabbitMQ for Mac OS Install
使用brew来安装 RabbitMQ brew install rabbitmq 执行看到如下命令: Updating Homebrew... ==> Auto-updated Homebrew ...
- golang语言示例
package main import "fmt" /* my first programmer in go */ func fib(n int) int{ if n<2{ ...