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. 数据保证不存在负权回路. 输入格式 ...
随机推荐
- 杭电ACM2022--海选女主角
海选女主角 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- SpringCloud-Eureka注册与发现
这两年可以说微服务是热词,也是新领域,学习的成本也较高,基础东西太多比如什么Dubbo,zookeeper,Springboot等等.Dubbo也是实现服务治理又是阿里出的一套开源RPC框架,但是Sp ...
- web.xml的<url-parttern>的匹配规则
<url-parttern>顾名思义是对url(统一资源定位符)的一种匹配,是对“http:........."地址的匹配,但是会减去应用上下文,就是你的web程序的名字,如果你 ...
- MySQL数据库中的四种隔离级别
事务的隔离性比想象的要复杂,在 SQL 标准中定义了四种级别的隔离级别.通常而言,较低级别的隔离通常可以执行更高的并发,系统的开销也更低 READ UNCOMMITTED 该级别为未提交读.在该级别中 ...
- 原生js实例对象方法
Array中的方法 ☞ toString() // 把数组转换为字符串,使用逗号分隔☞ valueOf() // 返回数组对象本身 ☞ 栈方法(先进后出)ary.push() // 该方法有一个返回值 ...
- 为什么 User 应该翻译为 「使用权人」 ?
User, 旧译「用户」,我在此向大家倡议有条件地选择翻译为「使用权人」. 1. __使用权人__更能反应 User 的本质特征 我们看到一匹马的时候不会说这是一头猪,而 User 的本质是什么?在我 ...
- Snapde电子表格编写Exprtk脚本进行数据运算
Snapde,一个专门为编辑超大型数据量CSV文件而设计的单机版电子表格软件:它运行的速度非常快,反应非常灵敏. 一.打开文件:用Snapde打开需要运算的CSV文件 二.添加行列:在编辑菜单找到设置 ...
- SSH实现登陆拦截器
/** * 登录验证拦截器 * */ @SuppressWarnings("serial") public class LoginInteceptor implements Int ...
- 【Java】itext根据模板生成pdf(包括图片和表格)
1.导入需要的jar包:itext-asian-5.2.0.jar itextpdf-5.5.11.jar. 2.新建word文档,创建模板,将文件另存为pdf,并用Adobe Acrobat DC打 ...
- Android探究之Gson@SerializedName
@SerializedName注解的意义 当我们使用Gson解析Json数据时都会创建一个对应实体类,有时候Json数据里面的字段是Java关键词或者Json数据里面的字段太简单,我们想在实体类中自定 ...