最短路径算法(II)
什么??你问我为什么不在一篇文章写完所有方法??
Hmm…其实我是想的,但是博皮的加载速度再带上文章超长图片超多的话…
可能这辈子都打不开了吧…
福特算法(Bellman-Ford)
适用范围及时间复杂度
单源最短路径算法,可处理负边权,但,无法处理负回路的情况。时间复杂度O(NE)
N:顶点数,E:边数
核心思想
松弛计算。什么是松弛计算?你戳…
……
aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABLAHkDASIAAhEBAxEB/8QAGwAAAQUBAQAAAAAAAAAAAAAABAECAwUGAAf/xAA0EAACAQIFAgUCBQMFAQAAAAABAhEAAwQFEiExQVEGEyJhgQdxFBVSkaEjMsEkM2Kx0fD/xAAZAQACAwEAAAAAAAAAAAAAAAABAgADBAX/xAAeEQACAgIDAQEAAAAAAAAAAAAAAQIRAyESMUEEE//aAAwDAQACEQMRAD8A9jVvVtx3p5bSDBioIiBzSajwP5rKaOKsl1g7dKY5gcTUbOFBnniq18U7XCupo6CYqyMOSsaqLRSdQk0+Y6TvVTbvsyn1sT71ML7MNmam4UQPF0ByBE01rg56dTQBusr6zJn3pxuOUJNNxXgtMP1+mBUb3CIKn5NCG8zCCNgOZpfMIQf3Ek1NJEDVcORuQfYxXOxUHqBzQAuMHEGD3miEYEEMx95ocd6CokjXwGAIO1R3GU7jrUVwjVKk+wpS5CgRzRpJ6J0cX5PNJ5x7fxTC0UkjvTp0GyxVgwESYprGH9Q27UwHTEGKT+/cgmsozobdILdKqCy6mLbCatLhPl7c96pTaZ7rCSQDWjElQrC7WkhjbYEU9DDDeCeYoYI8BVAAqewrqPWAOs1HrsDPPs5+qTYfH42xlmVHFYfCObVzFPc0gPuJC9QCPmKprP1ixqZYbf4FMTjS5/qPCWwvTYc9e1Wf1C8H5dgMpzDOcBh7qYzF3LaFEc6CXb1Np4E/5rGZX4LbGYmyLz/6a0ZvXQ49Z/QgB2H/ACPPSnlmilpFmPBKbs0WWfWTFWrrfm+VW3tNGlsKdBX4YkH+KtLP1ZxmJuOmAyUY5jbL27dskG2o3Jc78DmAN6yPifw1hr13GY7LMXaFxE8y7hAQdlG5EcbdDVL4NwOY5tm13AZabpF61/X0PoJs6hq9XQcUynGUbEy4pY57Pd/CHie14ryH8y/Dmw63DbuWydQVhvse0EVfC4XRtO3361UZF4fy/wANZYuXYBXFoOXZnaWZj1J+P4qwuBliIj71nclegonsmDIXpTrryAY3/ah7b+XB1bE0rnYbyDNGPdga2cXHE7e9d5g70yOvekn7ftTgLC2waQTxS6ih5371BbMKBNOJBX7jasxY0I9wlTHNU6vqJMmZqy/UBxVWWXzCQI36VqxdCMIS4QNzvRFt1uRJiKEUhuaJsQzRxUyLRDGfU3HqtjB4A6ghW5iGaCQSBCgx7z+1Z/K7NnSccLrXnuqQCLYB0mNjpHqjoTvWw8d4Ow35dj7l5rYtscO0Ho3qB+CvPT7Vh8VawuX3FvG0L2FuqNBQalFzrAGw1DfbqDWZpt0dT5XFY9kOMVMDhsRg7N4lb4aQFCrbEcAAVf8A0uyW1hr2OzexYZLVy2tmxcMgOJliPbZR96rrWQ3r1izmmK8lsLeYCzaW6Ha+ei7TC7ereQAetajwtnFyxf8AyXF3FbRAw1wKFlSJ0QOIgx7COlXRxuMSr7sn6vlBVFGy1qRzHemtcXed4HFQsjqoaRv2FcghZUye3UVXS9MIt0qEAMyfimo+u2omYmor5lxMn27UqMotDcRPMVckq0g+k2ojma6V/wDhUJfptS6l7VCXENZt9+OgplxxpADEe1IxIWD196EYknfp0qhKyPQWLgCxNVRhbhAbYHaiC5j44quFw64IH7VpwrQrCw4USePap7FxmYAEATQAYSF6Ci8OfVI71MvRKozvjF1vZ1luHJugpZuXA6baGkAGe5AYdqyuEyvDscdltzEXglx/NNnY+ljswJEiSN4iDWr8TejP8MxO17CMJ90ef+nrFX8wXB+LPPuQLYCYYtO2kyWJ+xKn4oWmjp4qUIhduzayPBYryterCgsoBkMrEeuONUAgkdqtTZYYJpIXEhNYujlHHqEewMVDm+CGIwd5lcpdS22llO5HVT3Bj/NCvmwu5W95UZLtxjZFtjJDnYb/AGM/aj2rDNqEZJnp+CxD4rLsLfuKFe9ZS4R2JUEj+aY6w/JBHEVKB5NhLSAabahPgCKGZmBg/MVTE5rEuagYLfNNRvRt0NOZYA32NMU+kg7DvVl6Qno7VPuZpPmk0g9KWPcftQWw0FI+rpt96hdtJO/vTQSJjpxXcsJ7VnToa77Gglu8zQ64Egkh9pmjF5HxTgNmPWnU34KlbBFwpBEsCO9SpZ0Ns3HtUs+meuqKcm4AqObYyVgWZ5Ic1t2NN/yL1li1t9GuJEEEHkHb9hWXzL6a43MhdfEZrhy7IqrowxVVIaSYB3mTNb+2ACIoi5/t/FLylYym10YrCeDcRh8s/B3cwW7CaFuG2dQWIg9+v8UJf8EacSLi4xAmlRp0HdgV9XP6VC1t25FB4kkHbvTKTJLJJ6bJrjE7jk9JpgwpeGDqWkejeT2+T0FK5IMChXJEwSNo/g0Ylcm6JndCAdSkTHO9NkOgKRHTfmozaRyiMCVEbSaccPaBYhY4PJ7H/wAoibsRnRAdTqAO5rtfuKj8pQo/u9QAPqNL5SfppkMr9P/ZAA==" 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( ...
随机推荐
- 使用OrgChart插件生成家谱组织结构图
1.orgchart插件: github地址:https://github.com/dabeng/OrgChart 2.前端代码: //1.加载树形数据:ajax请求获取json格式的数据(flag参 ...
- HTML5新特性之离线缓存技术
一.离线缓存的起因. HTML5之前的网页,都是无连接,必须联网才能访问,这其实也是web的特色,这其实对于PC是时代问题并不大,但到了移动互联网时代, 设备终端位置不再固定,依赖无线信号,网络的可靠 ...
- kali linux 安装 Mysql Can't read from messagefile 报错解决方案
1.下载安装包 下载地点:https://dev.mysql.com/downloads/mysql/ 或者 wget http://dev.mysql.com/get/Downloads/MySQL ...
- mysql中用HEX和UNHEX函数处理二进制数据的导入导出
读取数据并拼写sql语句,然后进行导入.具体方法为: (1)导出时采用HEX函数读取数据,把二进制的数据转为16进制的字符串: select HEX(binField) from testTable; ...
- 【转载】 旧版本Microsoft Office正在配置解决方法
原文:https://blog.csdn.net/sinat_37215184/article/details/81053931 在运行Microsoft Office 2010等旧版本的Office ...
- MVC Controller 基类 BaseController 中的 Request
今天修复mvc中的一个bug,需求是每个页面要获取当前URL链接中 host首是否正确,我把获取url的方法写到了Controller的基类BaseController(BaseController继 ...
- 自添加LUCI菜单及编译为ipk
目录 添加汉化编译为ipk配置文件入口函数界面文件Makefile 添加 添加自己的luci界面,有3个必要的要素: a配置文件.新建一个在/etc/config/abcdefg b入口函数.新建一个 ...
- C语言顺序表
顺序表结构可设为一个数组和一个指向尾部的变量,数组用来存放元素,指向尾部的变量在插入元素的时候加一,删除元素的时候减一,始终指向尾部. typedef int elemtype; typedef st ...
- HDL代码风格建议(1)使用示例和IP
Recommended HDL Coding Styles HDL coding styles can have a significant effect on the quality of resu ...
- 怎样才能使用ChipScope 加入被优化掉的信号
在调试过程中常常遇到的一个问题就是,xilinx工具在逻辑综合的过程中,将自己RTL代码中的很多变量都优化掉了,使得调试的抓信号的过程很纠结.以下是解决方法: 1.右键synthesis,在综合选项里 ...