Bellman-ford算法、SPFA算法求解最短路模板
Bellman-ford 算法适用于含有负权边的最短路求解,复杂度是O( VE ),其原理是依次对每条边进行松弛操作,重复这个操作E-1次后则一定得到最短路,如果还能继续松弛,则有负环。这是因为最长的没有环路的路,也只不过是V个点E-1条边构成的,所以松弛E-1次一定能得到最短路。因此这个算法相比 Dijkstra 首先其是对边进行增广,其次它能检测出负环的存在(若负环存在,那么最短路是取不到的,因为可以一直绕着这个负环将最小路径值不断缩小),这个弥补了 Dijkstra 的不足,但是其算法跑的比较慢,因此为了追求速度往往采用其“队列优化版”==>SPFA,因此想要理解SPFA最好先看看Bellman-ford算法。
SPFA 算法适用于含有负权边的最短路求解,其复杂度并没有网上传的那么神乎在理想情况下有论文指出其复杂度为O(kE)且k是一个约小于2的常数,但是在一些稠密图下其算法性能还是会退化到和 Bellman-ford 一样的 O( VE ),所以在稠密图下建议使用 Dij + Heap 优化的版本,稀疏图下 SPFA 还是很给力的!在 Bellman-ford 中发现啊最外层的 N-1 次循环未免盲目、实际上被松弛过的点我们希望其去继续松弛其他点,这样我们用队列将被松弛过的点存起来以便下一次继续松弛其他点,具体原理和做法可以参考下面的链接,顺便一提,SPFA还有两个优化==> SLF 与 LLL,具体也不阐述了。本文主要给出模板!
算法原理 or 学习参考链接 : 点我 、点我啦 、 点嘛!
Bellman-ford模板
///POJ 2387为例
#include<bits/stdc++.h>
using namespace std;
;
const int INF = 0x3f3f3f3f;
struct EdgeNode{ int from, to, w; };
EdgeNode Edge[maxn*maxn];
int Dis[maxn];
int N, M, cnt;
inline void init()
{
; i<=N; i++)
Dis[i] = INF;
cnt = ;
}
bool BellmanFord(int st)
{
Dis[st] = ;
; i<N; i++){///N-1 次循环后肯定能找出最短路
bool Changed = false;
int to, from, weight;
; j<cnt; j++){
to = Edge[j].to,
from = Edge[j].from,
weight = Edge[j].w;
if(Dis[from]!=INF && Dis[to] > Dis[from] + weight){
Changed = true;
Dis[to] = Dis[from] + weight;
///pre[to] = j; //Record paths
}
}
if(!Changed) return true;///如果没有边可以继续松弛了,说明算法结束且无负环
if(i==N && Changed) return false;///有负环
}
return false; ///一般来说绝无可能执行到这一步
}
int main(void)
{
while(~scanf("%d %d", &M, &N)){
init();
int from, to, weight;
; i<M; i++){
scanf("%d %d %d", &from, &to, &weight);
Edge[cnt].from = from;
Edge[cnt].to = to;
Edge[cnt].w = weight;
cnt++;
Edge[cnt].to = from;
Edge[cnt].from = to;
Edge[cnt].w = weight;
cnt++;
}
BellmanFord();
printf("%d\n", Dis[N]);
}
;
}
SPFA模板( SLF 优化版 )
///POJ 2387为例
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <string.h>
using namespace std;
const int INF=0x3f3f3f3f;
;
struct EdgeNode{ int v, w, nxt; };
EdgeNode Edge[maxn*maxn];
bool vis[maxn];
int Head[maxn], Dis[maxn], cnt;
int N, M;
/// int PushCnt[maxn]; ///记录每一个节点的入队次数、方便判断负环
inline void init()
{
; i<=N; i++)
///PushCnt[i] = 0;
Head[i] = -,
Dis[i] = INF,
vis[i] = false;
cnt = ;
}
inline void AddEdge(int from, int to, int weight)
{
Edge[cnt].w = weight;
Edge[cnt].v = to;
Edge[cnt].nxt = Head[from];
Head[from] = cnt++;
}
void SPFA(int st)///若要判断负环、改为 bool
{
deque<int> que;
que.push_back(st);
vis[st]=true;
Dis[st]=;
while (!que.empty())
{
int T=que.front(); que.pop_front();
vis[T]=false;
; i=Edge[i].nxt)
{
int v=Edge[i].v;
int w=Edge[i].w;
if (Dis[v]>Dis[T]+w){
Dis[v]=Dis[T]+w;
///p[v] = T;
if (!vis[v]){
///if(++PushCnt[v] > N) return false; //有负环
vis[v]=true;
if(!que.empty() && Dis[v] < Dis[que.front()]) que.push_front(v);
else que.push_back(v);
//que.push_back(v); ///无SLF优化是这样写的
}
}
}
}
/// return true;
}
int main(void)
{
while(~scanf("%d %d", &M, &N)){
init();
int from, to, weight;
; i<M; i++){
scanf("%d %d %d", &from, &to, &weight);
AddEdge(from, to, weight);
AddEdge(to, from, weight);
}
SPFA();
printf("%d\n", Dis[N]);
}
;
}
Bellman-ford算法、SPFA算法求解最短路模板的更多相关文章
- UESTC - 1987 童心未泯的帆宝和乐爷 (第k短路 A*算法+SPFA算法 模板)
传送门: http://www.qscoj.cn/#/problem/show/1987 童心未泯的帆宝和乐爷 Edit Time Limit: 10000 MS Memory Limit: ...
- 六度分离(floyd算法,SPFA算法,最短路—Dijkstra算法)
Time Limit : 5000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submission(s) ...
- (模板)hdoj2544(最短路--bellman-ford算法&&spfa算法)
题目链接:https://vjudge.net/problem/HDU-2544 题意:给n个点,m条边,求点1到点n的最短路. 思路: 今天学了下bellman_ford,抄抄模板.dijkstra ...
- Bellman-Ford算法与SPFA算法详解
PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- [板子]SPFA算法+链式前向星实现最短路及负权最短路
参考:https://blog.csdn.net/xunalove/article/details/70045815 有关SPFA的介绍就掠过了吧,不是很赞同一些博主说是国内某人最先提出来,Bellm ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- 用scheme语言实现SPFA算法(单源最短路)
最近自己陷入了很长时间的学习和思考之中,突然发现好久没有更新博文了,于是便想更新一篇. 这篇文章是我之前程序设计语言课作业中一段代码,用scheme语言实现单源最段路算法.当时的我,花了一整天时间,学 ...
- Bellman-Ford & SPFA 算法——求解单源点最短路径问题
Bellman-Ford算法与另一个非常著名的Dijkstra算法一样,用于求解单源点最短路径问题.Bellman-ford算法除了可求解边权均非负的问题外,还可以解决存在负权边的问题(意义是什么,好 ...
随机推荐
- hibernate 2 一对多、多对一 双向映射
多对一或一对多中,在多的一方维护关系效率高 一:java实体类 1.Classes.java package cn.gs.ly.school.entity; import java.util.Set; ...
- CSS3——边框 圆角 背景 渐变 文本效果
边框 圆角边框 盒阴影 边界图片 圆角 CSS3 圆角制作器 指定每个角 背景 多重背景图像 大小 图像的定位 背景剪裁 渐变 线性渐变(Linear Gradients)- 向下/向上/向左/向右/ ...
- python3 基本数据类型_2
#!/usr/bin/python3 #以下set,dict的方法py2无法运行 #创建set 集合,使用大括号 { } 或者 set() 函数创建 #注意:创建一个空集合必须用 set() 而不是 ...
- 应用安全 - Web框架 - 数据库管理 - phpMyAdmin - 漏洞汇总
CVE-2019-18622 Date: 2019.10.28 类型: SQL injection in Designer feature 影响范围: phpMyAdmin versions prio ...
- 【Linux开发】Linux动态链接库搜索路径问题
说明:下列内容是从网上获取的,未经验证,仅作参考之用 动态库的搜索路径搜索的先后顺序是: (1).编译目标代码时指定的动态库搜索路径:(2).环境变量LD_LIBRARY_PATH指定的动态库搜索路径 ...
- JGit、SvnKit - 版本提交日志(1)提取
1.相关开源jar包 1>使用JGIT访问git项目 2>使用SVNkit访问svn Git官方JGit使用教程指导 2.Git历史提交日志导出到文件 在项目根目录执行如下命令,将日志 ...
- Pycharm2019.1.3破解
搬运: T3ACKYHDVF-eyJsaWNlbnNlSWQiOiJUM0FDS1lIRFZGIiwibGljZW5zZWVOYW1lIjoi5bCP6bifIOeoi+W6j+WRmCIsImFzc ...
- UVA 11354 Bond 最小生成树 + lca
题意 给出一张图,q个询问,每次询问给出uv,找出一条路径,使这条路径上的最大边权是两点所有路径中最小,输出这个值 思路 很显然要先求出最小生成树,任意两点在最小生成树上有唯一路径,并且这条路径上的最 ...
- 剑指offer-栈的压入、弹出序列-栈和队列-python
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- 在SQL中存储过程的一般语法
一般分为十种情况,每种语法各不相同: 1. 创建语法 1 2 3 4 5 6 7 create proc | procedure pro_name [{@参数数据类型} [=默认值] [outp ...