最潮最短路算法:SPFA
来源:互联网 发布:matlab字符分割算法 编辑:程序博客网 时间:2024/06/08 18:40
首先理解单源最短路一滴概念(以下概念不作证明,证明自行baidu):
V:点集
E:边集
s:源点
u:当前起始定点
v:当前目标顶点
u->v:表示顶点u直接到达顶点v(经过边数==1)
u~>v:表示顶点u通过某一路径到达顶点v(经过边数>=1)
lo[u, v]:表示顶点u到顶点v既最短路径
d[v]:储存源点s到顶点v既最短路径估计值,下界就系lo[u, v]
w[u,v]:从u到v既一条直达路径既长度(边权)
lo[s, v] <= lo[s, u] + w[u, v]:三角不等式1
d[v] > d[u] + w[u, v]:三角不等式2
P<v0, v1, ......vk>:顶点v0到顶点vk既最短路径点集
松弛技术:当三角不等式2未到达下界(即等于)时,可以对d[v]进行松弛,即执行d[v] = d[u] + w[u,v]
松弛路径性质:P<v0, v1, v2, ........vk>为s到u既最短路径点集(v0为s, vk为u),如果p按照边(v0, v1), (v1, v2)..(vk - 1, vk)顺序进行松弛,呢个时候d[vk] = lo[s, vk]。
-------------------------------------------------------银蛋阉割线---------------------------------------------------------------
SPFA(Shoetest-Path-Faster-Algorithm),时间复杂度底编程复杂度超低,速度更加系唔系人甘品。
作为一种单源最短路算法,潮就潮在,功能上可以代替传统Dijkstra同埋Bellman-Ford。
点解可以甘样讲?
(以下对比前提:链接表储存方式)
传统Dijkstra通过两重循环,对每一个当前d[u]最小者连接既边进行松弛,每个点仅执行一次,呢个算法费时就费在每次揾d[u]最小者都要遍历一次成个点集V,即系费时O(|V|),仲有Dijkstra吾可以用于有负回路既图上面。
Bellman-Ford速度明显最慢,因为该算法硬性对每一条边进行|V| - 1次松弛检测,不过呢个算法可以系有负回路既图上用,因为呢个算法既核心系松弛路径性质,每条最短路最多有|V| - 1条边,所以每条边最多松弛|V| - 1次,如果进行第|V|次松弛检测既时候有一条边可以被松弛,就说明有负回路存在,所以可以判断差分约束系统有无解。
SPFA算法系采用队列同埋松弛技术,每次从队列头取出一点u,对u可直达既点v进行松弛检测,如果松弛成功,检查点v系唔系已经入队列,如果未入,将v压入队列尾,进行以上操作直到队列为空或者有一点进入队列次数为|V|。
SPFA可以代替传统Dijkstra系因为每次只将被松弛点放入队列,当无点被松弛既时候,即每一个d[u] == lo[s, u]。极大程度上减少不必要既松弛操作,速度比传统Dijkstra快。
代替Bellman-Ford系因为SPFA同样适用于路径松弛性质,当有一点进入队列次数为|V|既时候,同样可以证明有负回路存在。
下面比出无负回路图SPFA代码加注释:
#include <iostream>#include <vector>#include <cstdio>#include <cstdlib>#include <queue>#include <memory.h>using namespace std;#define MAXI 1011#define INFI 0x7fffffff#define LLD long longstruct V{ int v, w;//v, w[u, v]};vector<V> g[MAXI]; //邻接表int n, dis[MAXI];//|V|, d[]bool inQ[MAXI];//入队标记
void SPFA(int u)//源点{ int i, v, w; queue<int> Q;//队列 for (i = 0; i < n; i++)//初始化 { dis[i] = INFI; inQ[i] = false; } Q.push(u);//压入源点 inQ[u] = true; dis[u] = 0; while (!Q.empty())//队列不为空 { u = Q.front(); Q.pop(); inQ[u] = false; for (i = 0; i < g[u].size(); i++) { v = g[u][i].v; w = g[u][i].w; if (dis[v] - w > dis[u])//符合三角不等式2 { dis[v] = w + dis[u];//松弛操作 if (inQ[v] == false)//判断v系唔系队列 { Q.push(v);//唔系就入队列 inQ[v] = true; } } } }}
下面比一个例子:
就系甘样,其实就系大家非常熟悉既BFS,另外再加上松弛技术姐嘛。
负回路版本只需要加上一个数组记录每个点入队次数就得。
多谢收睇~~
- 最潮最短路算法:SPFA
- 最短路--SPFA算法
- 最短路SPFA算法
- 最短路: SPFA算法
- 单源最短路-SPFA算法
- spfa算法 最短路
- SPFA算法 求单源最短路
- SPFA最短路算法
- hdu2544 最短路(SPFA算法)
- spfa 算法 (单源最短路)
- 最短路算法(SPFA)
- SPFA算法之最短路。
- 关于最短路算法SPFA
- 最短路(SPFA)算法
- 最短路SPFA 算法详解
- SPFA算法 (最短路)
- 最短路【SPFA】算法模板
- 求单源最短路的SPFA算法
- 在网上发现一款很不错的JS编码工具,完善的编码智能提示,还可以运行调
- 动态规划解最长公共子序列问题
- Asp.Net 4.0 新特性之 使用自定义OutputCache Provider
- zarafa页面上英文汉化的方法
- 编写存储过程的作用是什么?
- 最潮最短路算法:SPFA
- 汇编原理6:opcode
- Android深入浅出学习笔记之进程等级相关
- Linux音频编程指南
- Hibernate 继承类 每棵树 具体的独立的表
- attribute用法
- 全国大学生电子设计竞赛相关帖子汇总【2009.8.5更新】
- html和xml传特殊字符的时候需要转义
- linux (fedora ubuntu)下安装星际译王