图——图的Floyd法最短路径实现
1,Dijkstra 算法一次性求得起始顶点到所有其它顶点的最短路径,如果想要求解任意两个顶点之间的最短路径,可将图中顶点作为起始顶点执行 n 次 Dijkstra 算法就可以了;
2,可能解决方案:

1,算法执行结束后,i 到 j 最短路径值存储于 dist[i][j] 中。最短路径前驱结点存储于 path[N][N] 中;
2,这种方法比较土;
3,问题的提法:
1,已知一个各边权值均大于 0 的带权有向图,对每一对顶点 vi != vj,求出 vi 与 vj 之间的最短路径值以及最短路径上的顶点;
4,Floyd 算法核心:
1,定义一个 n 阶方阵序列:

其中:

2,怀疑当前两个顶点间路径不是最短路径,因此 Floyd 算法尝试通过其他顶点中转、直到找到一个中转点的中转路径最短;
5,n 阶方阵中元素的意义:

1,都是由邻接方阵中的权值推得的;
2,此算法是通过递推的方式得到两个顶点间最短路径的;
3,把所有的顶点的中转路径都推导完了,也就得到最小路径了;
4,后面方阵的推导,包含着前面方阵的信息,且每次推导都是最小,直到推导了全部顶点,得到最终最短路径;
6,Floyd 算法精髓:

7,Floyd 算法的实现:

1,初始化:
1,本质:使用邻接矩阵初始化 A(-1);
2,A(0), ..., A(n-1) 矩阵推导:
1,本质:使用中转顶点逐步推导最短路径;
2,最外层是在说 A(k)矩阵的循环,循环推导完后,得到最短路径矩阵 A(n-1),即为所求;

8,如何记录最短路径上的各个顶点?
1,定义辅助矩阵:
1,int path[N][N]; // 路径矩阵
1,path[i][j] 表示 i 到 j 的路径上所经过的第 1 个顶点;
2,初始化:path[i][j] = -1; or paht[i][j] = j;
1,有直接的连接则设置为 j,表示经过的第一个顶点为终值顶点 j;
2,没有连接的两个顶点设置为 -1;
3,修改:
if( (dist[i][k] + dist[k][j]) < dist[i][j] )
{
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = paht[i][k];
}
1,if 条件为真,由 k 这个顶点中转可以得到一条更短路径,则由 i 到 j 这条路径上所经过的第一个顶点就是由 i 到 k 这条路径上经过的第一个顶点,因为由 k 中转了下;
2,路径矩阵示例:
1,由一个点的路径推至其它路径:

2,辅助矩阵和路径:

9,Floyd 最短路径算法实现:
/* floyd 每对结点之间最短路径算法,返回值为最短路径;核心为通过中转顶点寻找更短路径 */
SharedPointer< Array<int> > floyd(int x, int y, const E& LIMIT) // O(n*n*n)
{
LinkQueue<int> ret; if( ( <= x) && (x < vCount()) && ( <= y) && (y < vCount()) ) //顶点编号要合理
{
DynamicArray< DynamicArray<E> > dist(vCount()); // 定义二维数组,N*N DynamicArray< DynamicArray<int> > path(vCount()); // 最短路径的辅助数组 /* 定义二维数组 */
for(int k=; k<vCount(); k++)
{
dist[k].resize(vCount());
path[k].resize(vCount());
} /* 初始值设置 */
for(int i=; i<vCount(); i++)
{
for(int j=; j<vCount(); j++)
{
path[i][j] = -; // i 和 j 是没有边的 dist[i][j] = isAdjacent(i, j) ? (path[i][j]=j, getEdge(i, j)) : LIMIT; // 邻接了就设置,利用了逗号表达式,逗号表达式第一个参数是设置顶点,第二个是设置权值
}
} /* 推导最短路径矩阵 */
for(int k=; k<vCount(); k++)
{
for(int i=; i<vCount(); i++)
{
for(int j=; j<vCount(); j++)
{
/* 推导规则,用中间顶点中转数据,看是否有最短路径值 */
if( (dist[i][k] + dist[k][j]) < dist[i][j] )
{
dist[i][j] = dist[i][k] + dist[k][j]; // 如果得到最短路径,认为其可能是最短路径,要更新其值 path[i][j] = path[i][k]; // 通过 k 顶点可以找到最小值,则这个顶点找到了
}
}
}
} while( (x != -) && (x != y) ) // 推导到终止顶点为止
{
ret.add(x); // 最短路径上的各个顶点加到返回值中 x = path[x][y]; // 递归的将 path[x][y] 上经过的第一个顶点放入 x 中,然后在下一个递推中从 x 出发再递归处其它顶点;
} if( x != - )
{
ret.add(x); // 将最后的一个 x 加入返回值队列中,因为上面 x == y,终止了在返回队列中的加入,所以这里要加入
}
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Index <x, y> is invalid ...");
} /* 看看目标的两个最短值之间是否真的有最短路径 */
if( ret.length() < )
{
THROW_EXCEPTION(ArithmeticException, "There is no path from x to y ...");
} return toArray(ret);
}
10,小结:
1,Floyd 算法通过递推逐步求得所有顶点间的最短路径;
2,Floyd 算法的本质是通过中转顶点寻找更短的路径;
3,邻接矩阵是最短路径推导的起始矩阵;
4,路径矩阵记录了最短路径上的各个顶点;
图——图的Floyd法最短路径实现的更多相关文章
- c/c++ 图的创建及图的相关函数(链表法)
c/c++ 图的创建及图的相关函数(链表法) 图的概念 图由点和线组成 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来 点之间的线,分有方向和无方向 创建图 创建图,实际就是创建出节点 ...
- Floyd-Warshall求图中任意两点的最短路径
原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短 ...
- 图——图的Dijkstra法最短路径实现
1,最短路径的概念: 1,从有向图中某一顶点(起始顶点)到达另一顶点(终止顶点)的路径中,其权值之和最小的路径: 2,问题的提法: 1,给定一个带权有向图 G 与起始顶点 v,求从 v 到 G 中其它 ...
- 图——图的Prim法最小生成树实现
1,运营商的挑战: 1,在下图标出的城市间架设一条通信线路: 2,要求: 1,任意两个城市间都能够通信: 2,将架设成本降至最低: 2,问题抽象: 1,如何在图中选择 n - 1 条边使得 n 个顶点 ...
- 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)
洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\) \(10^9\) 的时代了吗?落伍了落伍了/ ...
- 最短路径(Floyd法)
最短路径法: 算法的主要思想是:单独一条边的路径也不一定是最佳路径. 从任意一条单边路径开始.所有两点之间的距离是边的权的和,(如果两点之间没有边相连, 则为无穷大). 对于每一对顶点 u 和 v,看 ...
- 图——图的Kruskal法最小生成树实现
1,最小生成树的特征: 1,选取的边是图中权值较小的边: 2,所有边连接后不构成回路: 2,prim 算法是以顶点为核心的,最下生成树最大的特征是边,但 prim 算法非要以顶点为核心来进行,有些复杂 ...
- 图-图的表示、搜索算法及其Java实现
1.图的表示方法 图:G=(V,E),V代表节点,E代表边. 图有两种表示方法:邻接链表和邻接矩阵 邻接链表因为在表示稀疏图(边的条数|E|远远小于|V|²的图)时非常紧凑而成为通常的选择. 如果需要 ...
- 15 图-图的遍历-基于邻接矩阵实现的BFS与DFS算法
算法分析和具体步骤解说直接写在代码注释上了 TvT 没时间了等下还要去洗衣服 就先不赘述了 有不明白的欢迎留言交流!(估计是没人看的了) 直接上代码: #include<stdio.h> ...
随机推荐
- cast() 函数进行类型转换
service_fee 字段定义:`service_fee` decimal(14,4) NULL DEFAULT NULL COMMENT '手续费金额,含税' , 需求:service_fee ...
- PHP基础教程 PHP的页面缓冲处理机制
PHP有很多机制.函数,其实就是魔术师,重复发挥好,其实甚至是简单应用,就会出现神奇的效果.兄弟连PHP培训 这里来讲一个ob_start()函数. ob_start()函数用于打开缓冲区,比如hea ...
- scrapy项目1:爬取某培训机构老师信息(spider类)
1.scrapy爬虫的流程,可简单该括为以下4步: 1).新建项目---->scrapy startproject 项目名称(例如:myspider) >>scrapy.cfg为项目 ...
- Spring Boot教程(十八)构建RESTful API
首先,回顾并详细说明一下在快速入门中使用的@Controller.@RestController.@RequestMapping注解.如果您对Spring MVC不熟悉并且还没有尝试过快速入门案例,建 ...
- eclipse设置代码上屏按键
摘要 eclipse默认设置下,当自动补全代码框弹出时,我们按下"."."空格"."Enter"."tab",被选中的代 ...
- python3.7--pycharm selenium自启360浏览器/360极速浏览器方法
写于:2019.01.02(实测日) 参考文档:https://blog.csdn.net/five3/article/details/50013159 一.下载360浏览器或360极速浏览器的Chr ...
- pycharm 调用turtle模块时,窗口闪屏不能显示
#如下代码时,在pycharm中运行时,窗口在程序结束后,直接关闭,不能看到绘制的图像. #在python自带的IDE中,在执行代码后,可以看到窗口的显示. import turtle t = tur ...
- sass scss less 的编译工具 koala
使用 koala 时注意事项: 1.目录中一定不能出现中文,否则就会报错 2.文件中如果出现中文(!注释也算) 开头一定要加 @charset "utf-8"; 否则就会出现无 ...
- java 栈和栈帧
文章转载自:http://www.tuicool.com/articles/URZrMnb jvm为每个新创建的线程都分配一个堆栈.堆栈以帧为单位保存线程的状态.jvm对堆栈只进行两种操作:以帧为单位 ...
- SpringMVC中mvc:view-controller的使用
1.重定向 <mvc:view-controller path="/" view-name="redirect:/admin/index"/> 即如 ...