最短路径算法(II)
什么??你问我为什么不在一篇文章写完所有方法??
Hmm…其实我是想的,但是博皮的加载速度再带上文章超长图片超多的话…
可能这辈子都打不开了吧…
福特算法(Bellman-Ford)
适用范围及时间复杂度
单源最短路径算法,可处理负边权,但,无法处理负回路的情况。时间复杂度O(NE)
N:顶点数,E:边数
核心思想
松弛计算。什么是松弛计算?你戳…

……
aaarticlea/jpeg;base64,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" alt="" />
好吧我说…
松弛计算之前,点B的值是8,但点A的值加上边上的权重2,得到点B的值是5,5<8,更新B为5。这个过程的意义是:找到了一条通向B更短的路线,且该路线先经过A,然后通过权重为2的边,到达点B。
当然,也会存在另一种情况:
在进行松弛计算之前,点B的值是6,点A加上点边上的权值4得到7>6,表示没有找到通向B点更短的路线,故B不需要更新。
这也就诠释了为什么算法不可以处理负权回路的情况。

使用松弛之后,发现程序陷入死循环。
代码实现
不难发现,在使用算法前,我们要去检验负权回路。我们需要不断地迭代以求解。
初始化
首先我们需要一个边集数组,暂定u表示起点,v表示终点,w表示权。而这个数组的长度为边的数量。
顶点数*(顶点数-1)/2。
什么?你不知道什么是边集数组?
边集数组
边集数组是利用一维数组存储图中所有边的一种图的表示方法。
该数组中所存储的元素个数要大于等于图中所有的边数。
每个元素用来存储图一条边起点,终点和权值。
struct edge{int s,e;double w;}edges[maxn*(maxn-)/];
特别注意的是:如果是无向图,则边的数量=顶点数量*(顶点数量-)/,加边函数为:
void addEdges(int u,int v,double w){
edges[++idx].s=u;edges[idx].e=v;edges[idx].w=w;
edges[++idx].e=u;edges[idx].s=v;edges[idx].w=w;
}
而在枚举边的时候,需要枚举idx条边。
定义边集数组时,特别要注意取值范围
边集数组是针对边的,如果题目给定了边的数量为n
,那么在无向邻接矩阵中,边集数组要定义为2*n+,
必须考虑来回。如果题目只给定了顶点数p,没有给定边数,
则边集数组的取值为:p*(p-)/
因为是无向图,算法第一层循环枚举点,第二层枚举边,所以加边函数的定义应是无向图的方法。
算法核心
void bellman(){
while(--n){
bool b=false;
for(int j=;j<=idx;j++){
if(dis[edges[j].e]>dis[edges[j].s]+edges[j].w){
dis[edges[j].e]=dis[edges[j].s]+edges[j].w;
b=true;
}
}
if(!b){
break;
}
}
}
----------7.22 Update
学个A*不知道扒出来了我多少学错了的东西…这篇里面提到了最基本的福特算法,但是有一个队列优化没有补充。我一直误以为SPFA是福特算法的别称,在这里做出纠正顺便优化一下之前乱七八糟的写法。
SPFA(队列优化的Bellman-Ford)
仅仅在大陆流行叫这个优化SPFA。优化过后,在随机数据的表现情况为O(KE),K是一个较小的常数。在特殊构造中,有可能被退化成O(NE)。
优化思想是:
1.建立一个队列,最初队列中只有一个起点1
2.取出队首节点x,扫描他的所有出边(x,y,z)。如果有Dis[y]>Dis[x]+z,则用后者更新前者。同时,若y不在队列中,将y入队
3.重复以上步骤,直至队列为空。
这个队列避免了福特算法中对不需要进行扩展的节点的冗余扫描。
void spfa()
{
memset(Distance,0x3f,sizeof(Distance));
memset(Vist,,sizeof(Vist));
Distance[]=;
Vist[]=;
q.push();
while(q.size())
{
int x=q.front();
q.pop();
Vist[x]=;
for(int i=head[x]; i; i=Edges[i].Next)
{
int y=Edges[i].End,z=Edges[i].Val;
if(Distance[y]>Distance[x]+z)
{
Distance[y]=Distance[x]+z;
if(!Vist[y])
{
q.push(y),Vist[y]=;
}
}
}
}
}
最短路径算法(II)的更多相关文章
- Johnson 全源最短路径算法
解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...
- Floyd-Warshall 全源最短路径算法
Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 几大最短路径算法比较(Floyd & Dijkstra & Bellman-Ford & SPFA)
几个最短路径算法的比较:Floyd 求多源.无负权边(此处错误?应该可以有负权边)的最短路.用矩阵记录图.时效性较差,时间复杂度O(V^3). Floyd-Warshall算法(Floyd ...
- 带权图的最短路径算法(Dijkstra)实现
一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...
- 无向图的最短路径算法JAVA实现
一,问题描述 给出一个无向图,指定无向图中某个顶点作为源点.求出图中所有顶点到源点的最短路径. 无向图的最短路径其实是源点到该顶点的最少边的数目. 本文假设图的信息保存在文件中,通过读取文件来构造图. ...
- 最短路径算法之Dijkstra算法(java实现)
前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...
- Floyd最短路径算法
看完这篇文章写的小程序,Floyd最短路径算法,求从一个点到另一个点的最短距离,中间可以经过其他任意个点.三个for循环,从i到j依次经过k的最短距离,最外层for循环是经过点K,内部两个循环是从i( ...
随机推荐
- careercup-扩展性和存储限制10.3
题目 给你一个文件,里面包含40亿个整数,写一个算法找出该文件中不包含的一个整数, 假设你有1GB内存可用. 如果你只有10MB的内存呢? 解答 我们先来做个算术题,40亿个整数大概有多大? * ^ ...
- HttpClient请求地址并携带参数
废话不多,直接上代码! /** * * @param httpUrl * @param reqInfo * @return */ public static StringBuffer sendPost ...
- 解决MyEclipse JAVA EE无法识别Base64问题
第一步:右击项目选择Build Path,选择Configure Build Path 第二步:点击JRE System Library选择右边的Edit 第三步:选择Alternate JRE,点击 ...
- 动态树LCT(Link-cut-tree)总结+模板题+各种题目
一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val: 令x点的点权变为val Query x y: 计算x,y之间的唯一的最短路径的点 ...
- MySQL 5.7基于GTID的主从复制
since i've broken down the replication enviornment by "reset master;" yesterday.th ...
- 单文件版本的netframework的net core 2.1
如果你还在用net4.5,如果你还在用netframework,又想使用netcore2.1的库或者功能,又觉得nuget动不动就好大,可以试试下面的这个. https://pan.baidu.com ...
- 慎使用sql的enum字段类型
在sql的优化中,会有同学提到一点:使用enum字段类型,代替其他tinyint等类型.以前这也是不少人喜欢优化的,但是现在细想,是非常不合理的. 优点: 1.可以设置区间范围,比如设置性别:1男2女 ...
- vue调用豆瓣API加载图片403问题
"豆瓣API是有请求次数限制的”,这会引发图片在加载的时候出现403问题,视图表现为“图片加载不出来”,控制台表现为报错403. 其实是豆瓣限制了图片的加载,我自己用了一个办法把图片缓存下来 ...
- OAuth2.0 与 oauth2-server 库的使用
作者:baiyi链接:https://www.jianshu.com/p/83b0f6d82d6c來源:简书 OAuth2.0 是关于授权的开放网络标准,它允许用户已第三方应用获取该用户在某一网站的私 ...
- STM32(11)——DMA
简介: DMA:Direct Memory Access,直接存储器访问.DMA传输数据从一个地址空间复制到另外一个地址空间.当CPU初始化这个传输动作,传输动作本身就是DMA控制器来实现和完成.典型 ...