最短路算法(3种算法)
1.最短路
最短路,顾名思义,最短的路径。我们把边带有权值的图称为带权图。边的权值可以理解为两点之间的距离。一张图中任意两点之间会有不同的路径相连。最短路径就是指连接两点的这些路径中最短的一条。我们有四种算法可以有效地解决最短路径问题,但是当出现负边权时,有些算法不适用。
2. Floyd算法(解决多源最短路径):时间复杂度O(n^3), 空间复杂度(n^2)
推荐一篇博客。写的非常易懂:Floyd
- 分类:多源最短路径算法。
- 作用:1.求最短路。 2.判断一张图中的两点是否相连。
- 优点:实现极为简单
- 缺点:只有数据规模较小且时空复杂度都允许时才可以使用
= 思想:3层循环,第一层枚举中间点k,第二层与第三层枚举两个端点i,j。若有dis[i][j] > dis[i][k] + dis[k][j] 则把dis[i][j]更新成dis[i][k] + dis[k][j](原理还是很好理解的)。 - 实现:
(a)初始化:点i,j如果有边相连,则dis[i][j] = w[i][j]。如果不相连,则dis[i][j] = 0x7fffffff(int极限值),表示两点不相连(或认为相隔很远)。
(b)算法代码:
for(int k = 1; k <= n; k++) //枚举中间点(必须放最外层)for(int i = 1; i <= n; i++) //枚举端点iif(i != k)for(int j = 1; j <= n; j++) //枚举端点jif(i != j && j != k && dis[i][j] > dis[i][k] + dis[k][j])dis[i][j] = dis[i][k] + dis[k][j];
完整代码
1 #include 2 int main() 3 { 4 int e[10][10],k,i,j,n,m,t1,t2,t3; 5 int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值6 //读入n和m,n表示顶点个数,m表示边的条数7 scanf("%d %d",&n,&m); 8 //初始化9 for(i=1;i<=n;i++)
10 for(j=1;j<=n;j++)
11 if(i==j) e[i][j]=0;
12 else e[i][j]=inf;
13 //读入边
14 for(i=1;i<=m;i++)
15 {
16 scanf("%d %d %d",&t1,&t2,&t3);
17 e[t1][t2]=t3;
18 }
19 //Floyd-Warshall算法核心语句
20 for(k=1;k<=n;k++)
21 for(i=1;i<=n;i++)
22 for(j=1;j<=n;j++)
23 if(e[i][j]>e[i][k]+e[k][j] )
24 e[i][j]=e[i][k]+e[k][j];
25 //输出最终的结果
26 for(i=1;i<=n;i++)
27 {
28 for(j=1;j<=n;j++)
29 {
30 printf("%10d",e[i][j]);
31 }
32 printf("\n");
33 }
34 return 0;
35 }
Floyd-Warshall算法不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路。
- 如果是一个没有边权的图,把相连的两点间距离设为dis[i][j] = true,不相连的两点设为dis[i][j] = false,用Floyed算法的变形:
for(int k = 1; k <= n; k++) //枚举中间点for(int i = 1; i <= n; i++) //枚举端点iif(i != k)for(int j = 1; j <= n; j++) //枚举端点jif(i != j && j != k)dis[i][j] = dis[i][j] || (dis[i][k] && dis[k][j]);(判断是否相连)
3. 迪杰斯特拉算法(解决单源最短路径)
- 分类:
单源最短路径算法。 - 适用于:
稠密图(侧重对点的处理)。 - 时间复杂度:
1.朴素:O(N^2)
2.堆优化:O(n * logn) - 缺点:
不能处理存在负边权的情况。 - 算法思想:
把点分为两类,一类是已经确定最短路径的点,称之为“标记点”;另一类则是还未确定最短路径的点,称之为“未标记点”。如果要求出一个点的最短路径,就是把这个“未标记点”变成“标记点”,从起点到“未标记点”的最短路径上的中转点在这个时刻只能是“标记点”。
Dijkstra的算法思想,就是一开始将起点到起点的距离标记为0,而后进行n次循环,每次找出一个到起点距离dis[u]最短的点u,将它从“未标记点”变为“标记的点”。随后枚举所有的“未标记的点”vi,如果以此“标记的点”为中转点到达“未标记的点”vi的路径dis[u] + w[u][vi]更短的话,这将它作为vi的“更短路径”dis[vi](此时还不确定是不是vi的最短路径)。
就这样,我们每找到一个“标记的点”,就尝试着用它修改其他所有的:“未标记的点”,故每一个终点一定能被它的最后一个中转点所修改,而求得最短路径。 - 优化思想:
利用堆(优先队列),把冗杂的枚举查找变成更加快速的堆直接弹出。 - 实现思路:
(a)初始化:dis[v] = oo (v != s); dis[s] = 0; pre[s] = 0;
(b)for(int i = 1; i <= n; i++)
1.在没有被访问过的点中找一个顶点u使得dis[u]是最小的。
2.u标记为已确定最短路径。
3.for与u相连的每个未确定最短路径的顶点v。
(伪代码)
if(dis[u] + w[u][v] < dis[v]){dis[v] = dis[u] + w[u][v];pre[v] = u;}
#define inf 99999999
/***构建邻接矩阵edge[][],且1为源点***/
for(i = 1; i <= n; i++) dst[i] = edge[1][s];
for(i = 1; i <= n; i++) book[i] = 0;
book[1] = 1;
for(i = 1; i <= n-1; i++){//找到离源点最近的顶点u,称它为新中心点min = inf;for(j = 1; j <= n; j++){if(book[j] == 0 && dst[j] < min){min = dst[j];u = j;}}book[u] = 1;//更新最短路径数组for(k = 1; k <= n; k++){if(edge[u][k] < inf && book[k] == 0){if(dst[k] > dst[u] + edge[u][k])dst[k] = dst[u] + edge[u][k]; }}
}
4. Bellman算法
- 分类:
单源最短路径算法。 - 适用于:
稀疏图(侧重于对边的处理)。 - 优点:
可以求出存在负边权情况下的最短路径。 - 缺点:
无法解决存在负权回路的情况。 - 时间复杂度:
O(NE),N是顶点数,E是边数。(因为和边有关,所以不适于稠密图) - 算法思想:
很简单。一开始认为起点是“标记点”(dis[1] = 0),每一次都枚举所有的边,必然会有一些边,连接着“未标记的点”和“已标记的点”。因此每次都能用所有的“已标记的点”去修改所有的“未标记的点”,每次循环也必然会有至少一个“未标记的点”变为“已标记的点”。 - 算法实现:
初始化:dis[s] = 0; dis[v] = oo(v != s); pre[s] = 0;
(伪代码)
for(int i = 1; i <= n - 1; i++)for(int j = 1; j <= E; j++) //注意要枚举所有边,不能枚举点if(dis[u] + w[j] < dis[v]) //u, v分别是这条边连接的两个点{dis[v] = dis[u] + w[j]pre[v] = u;}
最短路算法(3种算法)相关推荐
- 最短路的几种算法及其优化(模板)
一.Dijkstra 算法 dijkstra算法适用于边权为正的情况,求单源最短路,适用于有向图和无向图 模板伪代码: 清除所有点的标号 设d[0]=0,其余d[i]=INF: 循环n次{ 在所有未标 ...
- LCA 朴素算法+树差分倍增+Tarjan算法 三种算法实现c++代码实现
哔哩哔哩up视频:https://www.bilibili.com/video/BV1nE411L7rz?t=379 转载:http 文章目录 树差分 & 倍增LCA Tarjan 朴素算法 ...
- 最短路小结(三种算法+各种常见变种)
额,博主只是做了几(约数)道题而已,写这篇小结纯粹想留作纪念(勿喷,但是可以交流)(那啥,转载的话注明一下来源..打字不容易..) 最短路呢,包括三种算法,但是各有各的变种,其中变化有很多. 简单记录 ...
- python OpenCV 图片相似度 5种算法
原始两张图片: 代码运行结果如下. 5种算法 值哈希算法.差值哈希算法和感知哈希算法都是值越小,相似度越高,取值为0-64,即汉明距离中,64位的hash值有多少不同. 三直方图和单通道直方图的值为0 ...
- 【含泪提速!】一文全解相似度算法、跟踪算法在各个AI场景的应用(附代码)
大家好,我是cv君,大家是否为深度学习算法速度感到困扰?本次cv君倾力分享一个优秀的方法,通过相似度+跟踪方案优化速度问题,并提高了检测.分割算法稳定性,附带代码,一起肝起来吧~ 今天给大家全解一下图 ...
- 深入浅出:四种常用的最短路算法+两种常用生成树算法+网络流常用算法大礼包
文章目录 一.最短路径 1:Dijkstra & 堆优化 & why not 负权边? 2:Bellman-Ford:迭代与松弛 2(2): 进阶版:Spfa & why 队列 ...
- 爱因斯坦谜题解答(三种算法比较)
爱因斯坦谜题: 在一条街上有颜色互不相同的五栋房子,不同国籍的人分别住在这五栋房子力,每人抽不同品牌的香烟,喝不同的饮料,养不同的宠物.已知如下情况: 1. 英国人住红色房子里. 2. 瑞 ...
- 随机洗牌:哪一种算法是正确的?
2019独角兽企业重金招聘Python工程师标准>>> 原文 记得当年搞NOIp时,我犯过一个相当严重的错误:错误地把Floyd算法的i, j, k三层循环的位置顺序搞颠倒了.直到准 ...
- 最短路算法 :Bellman-ford算法 Dijkstra算法 floyd算法 SPFA算法 详解
本文链接 :http://www.cnblogs.com/Yan-C/p/3916281.html . 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并不低所以,本文的代码 存图只 ...
最新文章
- iOS架构-cocoapods打包静态库(依赖私有库、开源库、私有库又包含静态库)(14)
- 使用SKIP-GRANT-TABLES 解决 MYSQL ROOT密码丢失
- oracle性能优化总结
- 三、css 和 js 的装载与执行
- 是按压还是触摸_一文读懂,选联想还是华为?Matebook 14锐龙版和YOGA 14s、小新Pro13怎么选?...
- 并发高?可能是编译优化引发有序性问题
- gridsearchcv参数_Python机器学习库Sklearn系列教程(21)-参数优化
- mysql 函数 数字转字串_mysql中字符串和数字的互转函数
- terminal采用公钥免密访问服务器
- 优秀技能经验及对java学习展望
- teraterm 执行sql_teraterm自动或定时执行远程命令
- 对于学习编程,你认为英语和数学哪个重要?
- Blue Coat:2015年数据安全趋势七大预测
- html中引用名言标签,CSS3 培根名人名言引用全屏居中样式设计
- Oracle 查询一个小时之前表的数据
- matlab读int16读文件_[转载]Matlab中的textread textscan读取文本文件
- 可以看游资的app_新游资APP:高评分App是如何养成的?
- python如何创建一个文件夹_利用Python怎么创建一个文件夹
- 高效办公!Python 批量生成PDF文档
- 「需求工程」需求工程-介绍(第1部分)
热门文章
- 基于jquery的带事件显示功能的日历板插件calendar.js
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- jquery click点击事件重复执行多次
- BZOJ 3404: [Usaco2009 Open]Cow Digit Game又见数字游戏(博弈论)
- Swift学习笔记(10)--枚举
- 记次浙大月赛 134 - ZOJ Monthly, June 2014
- Android开发14——监听内容提供者ContentProvider的数据变化
- CnBlogs自定义博客样式
- [数据结构]-循环队列
- pdoModel封装