弗洛伊德算法(Floyd)主要针对多源最短路径,且可以解决路径中有负权的情况(不包含负权回路),但是迪杰斯特拉算法只能解决正权值的单源最短路径(可以迭代多次求多源)。

1.弗洛伊德算法的基本思想

弗洛伊德算法从图的带权邻接矩阵cost出发,
假设求从顶点viv_{i}vi​到vjv_{j}vj​的最短路径:
如果从viv_{i}vi​到vjv_{j}vj​有弧,则从viv_{i}vi​到vjv_{j}vj​存在一条长度为arcs[i][j]的路径,但是不一定是最短的,还需进行n次试探。

  • 首先考虑k=0k=0k=0时,路径(vi,v0,vj)(v_{i},v_{0},v_{j})(vi​,v0​,vj​)是否存在,若存在则判断(vi,vj)(v_{i},v_{j})(vi​,vj​)和(vi,v0,vj)(v_{i},v_{0},v_{j})(vi​,v0​,vj​)的路径长度较短者,为从viv_{i}vi​到viv_{i}vi​的中间顶点的序号不大于0的最短路径;
  • 假设在路径上再增加一个节点v1v_{1}v1​,也就是说如果(vi,...,v1)(v_{i},...,v_{1})(vi​,...,v1​)和(v1,...,vj)(v_{1},...,v_{j})(v1​,...,vj​)分别是当前找到的中间顶点的序号不大于0的最短路径,那么(vi,...,v1,...,vj)(v_{i},...,v_{1},...,v_{j})(vi​,...,v1​,...,vj​)就有可能是从viv_{i}vi​到vjv_{j}vj​中间的顶点的序号不大于1的最短路径。将它和从viv_{i}vi​到vjv_{j}vj​中间的顶点的序号不大于0的最短路径,从中选最小者为最后从viv_{i}vi​到vjv_{j}vj​中间的顶点的序号不大于1的最短路径;
  • 依次类推,逐渐增加中间顶点的序号值到n−1n-1n−1,则经过nnn次比较后可求得从viv_{i}vi​到vjv_{j}vj​的最短路径。

2.弗洛伊德算法的基本表示

弗洛伊德算法属于动态规划算法的一种,而动态规划算法的关键是:

  • 如果将原问题划分为子问题?
    即如何确定子问题的状态
  • 如何通过子问题的求解得到原问题的解?
    即如何建立状态转移方程(我喜欢叫它动态规划的递归方程)。
    通过1的分析,我们可以这样来定义一个子问题:
    即定义一个n阶方阵序列:
    D−1,D0,D1,...,Dk,...,Dn−1D^{-1},D^{0},D^{1},...,D^{k},...,D^{n-1}D−1,D0,D1,...,Dk,...,Dn−1
    其中,DkD^{k}Dk表示当前求得的最短路径权值矩阵。
    动态递归方程

    其中,D(k)[i][j]D^{(k)}[i][j]D(k)[i][j]表示从v[i]v_[i]v[​i]到vjv_{j}vj​的中间顶点的序号不大于k的最短路径的长度。D(n−1)[i][j]D^{(n-1)}[i][j]D(n−1)[i][j]就是我们最后要求的从viv_{i}vi​到vjv_{j}vj​的最短路径。

3.弗洛伊德算法的实现

有了动态递归方程和初始条件,我们就可以编写代码像解数列公式一样求出各对顶点间的最短路径。
只需注意问题的初始化和主变量的确定,这个问题的主变量是中间顶点的标号,应该将其放在最外层循环,就像数列递推公式的下标一样。
为了存储最短路径序列,我们还需要一个数组path,且path[v][w]存储vvv到www的最短路径上vvv的后继节点,初始化为www。最后可以通过递归打印vvv到www的最短路径。

关键代码:

void ShortestPath_FLOYD(MGraph G, int** path, int**distance) {// 初始化int u, v, w;for ( u = 0; u < G.vexnum; u++) {for (v = 0; v < G.vexnum; v++) {distance[u][v] = G.arcs[u][v];path[u][v] = v;}}// 3个FOR循环更新ditance共n-1次for (u = 0; u < G.vexnum; u++) {for (v = 0; v < G.vexnum; v++) {for (w = 0; w < G.vexnum; w++) {// 设置中间变量,防止整数溢出;// 当然,若非邻接顶点的表示不是INT_MAX,而是一个非最大值的大数则不用int temp = (distance[v][u] == INT_MAX || distance[u][w] == INT_MAX) ?INT_MAX : (distance[v][u] + distance[u][w]);if (temp < distance[v][w]) {distance[v][w] = temp;path[v][w] = path[v][u]; // 更新v的直接后继}}}}
}

完整代码:

#include <iostream>
#include <string>using namespace std;#define MAX_VEX_NUM 50
// 定义图的邻接矩阵存储
typedef struct MGraph {int arcs[MAX_VEX_NUM][MAX_VEX_NUM];string vexs[MAX_VEX_NUM];int arcnum, vexnum;
}MGraph;
void createGraph(MGraph& G);
int locate(MGraph G, string u);
void showMatrix(MGraph G);
void ShortestPath_FLOYD(MGraph G, int** path, int**distance);
void showPath(MGraph G,int** path, int start, int end); //打印start-end的最短路径
int main() {MGraph G;createGraph(G);showMatrix(G);int** path; // 记录各个最短路径的信息int** distance; // 记录权值矩阵path = new int*[G.vexnum];distance = new int*[G.vexnum];for (int i = 0; i < G.vexnum; i++) {path[i] = new int[G.vexnum];distance[i] = new int[G.vexnum];}ShortestPath_FLOYD(G, path, distance);cout << "path矩阵:\n";for (int i = 0; i < G.vexnum; i++) {for (int j = 0; j < G.vexnum; j++) cout << path[i][j];cout << endl;}showPath(G, path,0, 2);// 释放内存for (int i = 0; i < G.vexnum; i++) {delete[] path[i];delete[] distance[i];}delete[] path;delete[] distance;system("pause");return 0;
}
void showPath(MGraph G,int** path, int start, int end) {int begin = path[start][end];cout << G.vexs[start] << "到" << G.vexs[end] << "的最短路径:\n";cout << G.vexs[start];while (begin != end) {cout << "-->" << G.vexs[begin];begin = path[begin][end]; // 迭代后半段}cout << "-->" << G.vexs[end] << endl;
}
void showMatrix(MGraph G) {cout << "图的邻接矩阵:\n";for (int i = 0; i < G.vexnum; i++) {for (int j = 0; j < G.vexnum; j++) {if (G.arcs[i][j] == INT_MAX)cout << "oo" << " ";else cout << G.arcs[i][j] << " ";}cout << endl;}
}
void createGraph(MGraph& G) {cout << "输入图的顶点数和边数:\n";cin >> G.vexnum >> G.arcnum;cout << "输入图的顶点信息:\n";int i;for (i = 0; i < G.vexnum; i++) cin >> G.vexs[i];// 初始化邻接矩阵int j;for (i = 0; i < G.vexnum; i++) {for (j = 0; j < G.vexnum; j++)G.arcs[i][j] = INT_MAX;}cout << "输入图的边的权值信息vi vj weight:\n";for (i = 0; i < G.arcnum; i++) {string v1, v2;int weight;cin >> v1 >> v2 >> weight;int l1 = locate(G, v1);int l2 = locate(G, v2);G.arcs[l1][l2] = weight;}
}

测试用例:

3 5
V0 V1 V2
V0 V1 4
V0 V2 11
V1 V0 6
V1 V2 2
V2 V0 3

即带权有向图:

参考资料

《数据结构 C语言描述》 严蔚敏著

最短路径之弗洛伊德算法(Floyd)——动态规划相关推荐

  1. 最短路径三大算法——1,弗洛伊德算法floyd(复杂度O(n^3))

    目前已经更新: 1,弗洛伊德算法floyd(复杂度O(n^3)) 2,迪杰斯特拉算法dijkstra (复杂度O(最坏n^2)) 3,SPFA算法(复杂度O(n*m)) 当然,最短路径有通用的bfs, ...

  2. 最短路径算法——清晰简单的弗洛伊德算法(Floyd)

    弗洛伊德算法(Floyd) \qquad 上一篇文章介绍了迪杰斯特拉算法(Dijkstra).具体请看:最短路径算法--简单明了的迪杰斯特拉算法(Dijkstra).Dijkstra适用于非负权图,并 ...

  3. 全源最短路径之弗洛伊德算法(C语言)

    Floyd(弗洛伊德)算法 该算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包. 时间复杂度为 O(N^3) 空 ...

  4. (王道408考研数据结构)第六章图-第四节5:最短路径之弗洛伊德算法(思想、代码、演示、答题规范)

    文章目录 一:动态规划基本思想 二:弗洛伊德(Floyd)算法基本思想 三:弗洛伊德(Floyd)算法代码实现 四:弗洛伊德(Floyd)算法代码视频演示 五:弗洛伊德(Floyd)算法代码答题规范 ...

  5. 图解最短路径之弗洛伊德算法(Java实现)

    概述 Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法是一种在具有正或负边缘权重(但没有负环)的加权图中找到最短路径的 ...

  6. 最短路径(弗洛伊德算法)

    1 原理 ,假设存在一个最简单的连通图 2 代码 package leaning.graph;/** * 弗洛伊德算法求最短路径* * */ public class Floyd {// 表示V0顶点 ...

  7. 两点之间最短路径:弗洛伊德算法

    弗洛伊德算法是计算无向有权图中两点间最短路径的算法,复杂度为O(n^3).其思路是将两点间距离分为过(指定的)第三点或是不过,然后取它们的最小值,如此循环就可以得到两点之间真正的最小值. void f ...

  8. 弗洛伊德算法Floyd

    全知识整理目录 数据结构整理的目录包括了许多的数据结构相关知识. 目录 概述 算法过程 关键代码的实现 总结 参考 概述 Floyd算法是什么? Floyd算法也是动态规划的求最短路径,但不同于Dij ...

  9. 最短路径之弗洛伊德算法

    [1]为什么需要弗洛伊德算法? 带权图中单个源点到所有顶点的最短路径问题可以用<迪杰斯特拉算法>求解. 那如果要求图中每一个顶点与其它顶点之间的最短路径呢?类似可以想到的方法为: 每次以一 ...

最新文章

  1. 关于面向对象的总结和疑惑(转载可乐冰
  2. python可以自学吗-没学过编程可以自学python吗
  3. 第15章-输入/输出 --- 理解Java的IO流
  4. Zookeeper分布式一致性原理(三):Chubby分布式锁服务
  5. python硬件交互_对Python的交互模式和直接运行.py文件的区别详解
  6. 【转】Lucene 工作原理
  7. 窥探JBoss Fuse 6.1的新功能
  8. 20 WM配置-策略-定义出库排序序列(拣配)
  9. linux目录结构及作用详图
  10. 对比解析开源云平台:Eucalyptus VS OpenStack
  11. 教孩子学编程 python 下载_教孩子学编程 python语言版
  12. 利用Python白玩steam游戏,我是专业的
  13. 随机森林 matlab
  14. 线下活动报名|增长骇客:如何利用数据「玩」出新意
  15. Excel实现数据项校验的功能---VBA的编写以及数据有效性的设置
  16. Dominating Patterns UVALive - 4670 (ac自动机)
  17. 像素三国志在线html5小游戏,激萌三国志H5
  18. 什么是Armbian
  19. 融云红包上线 要让每一款App都能“抢红包”
  20. SPI通信协议详解,一篇就够!

热门文章

  1. 彻底关闭苹果系统更新_彻底关闭iPhone自动更新系统 亲测有效
  2. Unity根据文字内容自动滚动显示最新文字
  3. 计算机无法进入增值税认证平台,增值税发票综合服务平台热点问题解答 (第三期)...
  4. 软件测试工程师简历编写规范
  5. 工作流调度系统Apache DolphinScheduler介绍和设计原理
  6. 单手杀穿经典链表题Pt.2——LeetCode天梯渡劫(倒数第k节点,合并链表,链表分割,回文结构)
  7. 创建群晖共享文件夹,并进行电脑访问
  8. acs2go android,Aquarius2Go Astrology
  9. ZooKeeper安装教程
  10. 本地服务:无法访问此网站 localhost 拒绝了我们的连接请求。ERR_CONNECTION_REFUSED