Floyd算法详讲
来源:互联网 发布:宝马5系改装轮毂数据 编辑:程序博客网 时间:2024/06/05 00:09
Floyd–Warshall(简称Floyd算法)是一种著名的解决任意两点间的最短路径(All Paris Shortest Paths,APSP)的算法。从表面上粗看,Floyd算法是一个非常简单的三重循环,而且纯粹的Floyd算法的循环体内的语句也十分简洁。我认为,正是由于“Floyd算法是一种动态规划(Dynamic Programming)算法”的本质,才导致了Floyd算法如此精妙。因此,这里我将从Floyd算法的状态定义、动态转移方程以及滚动数组等重要方面,来简单剖析一下图论中这一重要的基于动态规划的算法——Floyd算法。
Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。
来看看代码:
for ( int i = 0; k < 节点个数; ++i ){ for ( int j = 0; i < 节点个数; ++j ) { for ( int k = 0; j < 节点个数; ++k ) { if ( Dis[i][k] + Dis[k][j] < Dis[i][j] ) { // 找到更短路径 Dis[i][j] = Dis[i][k] + Dis[k][j]; } } }}
Floyd算法本质上是DP,即对于每个(可能的)新增的节点k,来更新(可能的)节点i到j的最短距离。
那就有人要问了,为什么新增节点 k 的循环要放在最外层呢? 因为如果放到内层,这样便过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。
用图来举个例子:
图中红色数字代表权值,如果我们在内层检查所有节点时,我们只能发现一条路径A->B,距离为9,显然这样是不正确的,正确的最短路径是A->D->C->B,路径距离为6。之所以这样就是因为把检查所有节点的循环放到了内层,造成了找到一条路径就过早的确定下来,而这一条路径不一定是最短路径。
如果还不明白,举个实例:
代码://Floyd#include<set>#include<queue>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define FOR(i,n,x) for(int i=x; i<=n; i++)#define Inf 1<<29using namespace std;int mp[100][100],n,m;int main(){ while(~scanf("%d%d",&n,&m)!=EOF) { FOR(i,n,1) { FOR(j,n,1) { if(i!=j) mp[i][j]=Inf; else mp[i][j]=0; } } FOR(i,m,1) { int a,b,c; scanf("%d%d%d",&a,&b,&c); mp[a][b]=c; } FOR(k,n,1)//枚举任意一对节点 { FOR(i,n,1)//起点 { FOR(j,n,1)//终点 { if(i!=j && j!=k) { mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); } } } } FOR(i,n,1) { FOR(j,n,1) { printf("dis %d %d = %d\n",i,j,mp[i][j]); } } } return 0;}
算法时间复杂度O(n3)
输入
4 41 4 14 2 34 3 13 2 1
输出
dis 1 1 = 0dis 1 2 = 3dis 1 3 = 2dis 1 4 = 1dis 2 1 = 536870912dis 2 2 = 0dis 2 3 = 536870912dis 2 4 = 536870912dis 3 1 = 536870912dis 3 2 = 1dis 3 3 = 0dis 3 4 = 536870912dis 4 1 = 536870912dis 4 2 = 2dis 4 3 = 1dis 4 4 = 0
Floyd算分的优缺点:
Floyd算法适用于APSP(All Pairs Shortest Paths,多源最短路径),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法,也要高于执行V次SPFA算法。
优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据
局限性:floyd算法可以有负权值的边,但不能有包含负权值边组成的回路
参考:
http://chenchuangfeng.iteye.com/blog/1816976
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
http://blog.csdn.net/start0609/article/details/7779042
http://blog.csdn.net/niushuai666/article/details/6772706
http://nopainnogain.iteye.com/blog/1047818
http://blog.csdn.net/earbao/article/details/8114861
http://blog.csdn.net/roofalison/article/details/5651806
- Floyd算法详讲
- Floyd算法详讲
- Floyd算法详讲
- KMP算法详讲
- 十三周 项目一 运行所讲算法,观察结果并领会算法(Floyd)
- Floyd算法
- Floyd算法
- Floyd算法
- Floyd算法
- Floyd算法
- Floyd算法
- Floyd算法
- Floyd算法
- floyd 算法
- Floyd算法
- floyd算法
- Floyd算法
- Floyd算法
- 每天一个linux命令之top命令
- spring框架学习(二)依赖注入
- I/O多路转接之select
- MongoDB常用操作命令大全
- ScrollView 嵌入Listview,当Listview中的Textview多余一行,高度如何重新计算
- Floyd算法详讲
- <oracle.adf.view> <SimpleSelectOneRenderer> <_getSelectedIndex> <Could not find selected item matchi
- 【Linux】linux定时清除N天之前的文件,一般用于清除日志文件
- 使用 MaxScale实现读写分离
- 学习转载系列-《自定义View基础-坐标系》
- BZOJ1634: [Usaco2007 Jan]Protecting the Flowers 护花
- stdio.h头文件包含的函数有哪些?
- 使用Xcode 7进行单元测试
- 亲测 能用的maven 镜像地址