Floyd最短路(带路径输出)

摘要(以下内容来自百度)

Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。

该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。

简介编辑

在计算机科学中,Floyd-Warshall算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路径的算法。算法的单个执行将找到所有顶点对之间的最短路径的长度(加权)。 虽然它不返回路径本身的细节,但是可以通过对算法的简单修改来重建路径。 该算法的版本也可用于查找关系R的传递闭包,或(与Schulze投票系统相关)在加权图中所有顶点对之间的最宽路径。

Floyd-Warshall算法是动态规划的一个例子,并在1962年由Robert Floyd以其当前公认的形式出版。然而,它基本上与Bernard Roy在1959年先前发表的算法和1962年的Stephen Warshall中找到图形的传递闭包基本相同,并且与Kleene的算法密切相关 在1956年)用于将确定性有限自动机转换为正则表达式。算法作为三个嵌套for循环的现代公式首先由Peter Ingerman在1962年描述。

该算法也称为Floyd算法,Roy-Warshall算法,Roy-Floyd算法或WFI算法。 [2]

核心思路编辑

路径矩阵

通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。 [3]

从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

采用松弛技术(松弛操作),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);

状态转移方程

其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]};

map[i,j]表示i到j的最短距离,K是穷举i,j的断点,map[n,n]初值应该为0,或者按照题目意思来做。

当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路。

算法过程编辑

1,从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。

2,对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。

把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i][j]=d,d表示该路的长度;否则G[i][j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i][j]表示从Vi到Vj需要经过的点,初始化D[i][j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i][j] = min( G[i][j], G[i][k]+G[k][j] ),如果G[i][j]的值变小,则D[i][j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。

比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。 [4]

时间复杂度与空间复杂度编辑

时间复杂度:O(n^3);

空间复杂度:O(n^2)

优缺点分析编辑

Floyd算法适用于APSP(All Pairs Shortest Paths,多源最短路径),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法,也要高于执行|V|次SPFA算法。

优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。

缺点:时间复杂度比较高,不适合计算大量数据。 [5]

关键的路径输出

例如

具体看代码

代码

#include<bits/stdc++.h>
using namespace std;
const int inf=999999;
int mp[20][20],path[20][20];
int n,m;
void print(int a,int b){
    if(path[a][b]==-1) return;//因为开始初始化为-1,这里就可以避免相邻的再次输出
    print(a,path[a][b]);//前半部
    cout<<path[a][b]<<"-->";//输出该点
    print(path[a][b],b);//后半部
}
int main(){
//freopen("in.txt","r",stdin);
  while(cin>>n>>m){
    memset(path,-1,sizeof(path));//初始化-1
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++) if(i==j) mp[i][j]=0;
     else mp[i][j]=inf;
   int Start,End,dis;
  for(int i=0;i<m;i++)
     {
        cin>>Start>>End>>dis;
        mp[Start][End]=dis;
 }
 //三层循环
 for(int k=1;k<=n;k++)
 {
    //第k个点进行松弛
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(mp[i][j]>mp[i][k]+mp[k][j])//如果能够缩短就更新距离
    {
        mp[i][j]=mp[i][k]+mp[k][j];
        path[i][j]=k;//记录能松弛的点
     }
  }
 cout<<"The shortest path between vertices\n";
 for(int i=1;i<=n;i++)
 for(int j=1;j<=n;j++)
 {
    if(mp[i][j]==inf){//两者不通
        cout<<i<<‘ ‘<<j;
        cout<<" These two points cannot be reached\n\n"; continue;
     }
    cout<<i<<" to "<<j<<" shortest path is "<<mp[i][j]<<endl;
    cout<<"The specific path is\n";
    cout<<i<<"-->";
    print(i,j);
    cout<<j<<‘ ‘;
    cout<<endl<<endl;
 }
}
return 0;
}
//输入数据
/*
10 14
1 2 45
1 3 35
1 4 50
2 3 20
2 6 50
2 9 70
2 5 50
4 5 50
6 7 20
6 8 50
6 9 50
7 1 40
7 4 40
10 9 35
*/ 

原文地址:https://www.cnblogs.com/mch5201314/p/10139993.html

时间: 2024-10-12 14:36:42

Floyd最短路(带路径输出)的相关文章

HDU 1385 Minimum Transport Cost(Floyd 最短路 打印路径)

HDU 1385 大意: 有N个城市,然后直接给出这些城市之间的邻接矩阵,矩阵中-1代表那两个城市无道路相连,其他值代表路径长度. 如果一辆汽车经过某个城市,必须要交一定的钱(可能是过路费). 现在要从a城到b城,花费为路径长度之和,再加上除起点与终点外所有城市的过路费之和. 求最小花费,如果有多条路经符合,则输出字典序最小的路径. 思路: Floyd求最短路,打印路径即可. 1 /*--------------------------------------------------------

ACM学习之路___HDU 1385(带路径保存的 Floyd)

Description These are N cities in Spring country. Between each pair of cities there may be one transportation track or none. Now there is some cargo that should be delivered from one city to another. The transportation fee consists of two parts: The

【啊哈!算法】算法6:只有五行的Floyd最短路算法

暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有4个城市8条公路,公路上的数字表示这条公路的长短.请注意这些公路是单向的.我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径.这个问题这也被称为“多源最短路径”问题. 现在需要一个数据结构来存储图的信息,我们仍然可以用一个4*4的矩阵(二维数组e)来存储.比如1号城市到2号城市的路程为2,则设e[1][2]

poj2607Fire Station(floyd最短路)

题目链接: 啊哈哈,点我带我 这道题目当时一看觉得很熟悉,但是后来越想越混乱,搞得最后题目都没搞清楚...比赛的时候不知道怎么想的,但是大致思想是对的.... 题意: 这道题目是讲原来镇上有若干个加油站,但是镇上的居民觉得消防站的距离李自己家太远,所以决定在居民点键一个消防站,要使离居民点的最大距离最小.. 思路:毫无疑问是最短路...但是这题数据太多..所以预处理的时候用floyd求出两个 任意两点间的距离,然后用加油站去更新到到各个居民点的最短距离..那么枚举所有加油站后就会得到所有到居民点

vijos1635 SPFA和FLOYD算法如何打印路径

之前打的spfa或是floyd都只是用来求最短路,对于如何打印路径问题一点都没有概念 可能也是因为对于原理没有很理解的缘故? 总之,之后赶紧看了一下,现在总算是明白了.....MARK一下自己的理解 早晨碰到了一题挺裸的最短路问题:vijos1635 1.首先说说spfa的方法: 其实自己之前打的最多的spfa是在网格上的那种,也就是二维的 一维的需要邻接表+queue 以及对于queue的操作,自己也是醉了 这里贴一个模板(不含打印路径): #include<cstdio> #include

POJ 1041 John&#39;s trip 无向图的【欧拉回路】路径输出

欧拉回路第一题TVT 本题的一个小技巧在于: [建立一个存放点与边关系的邻接矩阵] 1.先判断是否存在欧拉路径 无向图: 欧拉回路:连通 + 所有定点的度为偶数 欧拉路径:连通 + 除源点和终点外都为偶数 有向图: 欧拉回路:连通 + 所有点的入度 == 出度 欧拉路径:连通 + 源点 出度-入度=1 && 终点 入度 - 出度 = 1 && 其余点 入度 == 出度: 2.求欧拉路径 : step 1:选取起点(如果是点的度数全为偶数任意点为S如果有两个点的度数位奇数取一

HDU 1026 Ignatius and the Princess I(BFS+路径输出)

Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 19800    Accepted Submission(s): 6452Special Judge Problem Description The Princess has been abducted by the BEelzebub

java中如何创建带路径的文件

请教各位大侠了,java中如何创建带路径的文件,说明下 这个路径不存在 ------回答--------- ------其他回答(2分)--------- Java code File f = new File("c:/1.txt"); if(!f.exists()){ try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } ------其他回答(18分)--------- Java cod

URAL 1183 Brackets Sequence DP 路径输出

题意:长度小于100的字符串s只由四种字符"()[]"组成,求以该串为子串的最短的合法串.合法串递归定义为: (1)空串合法 (2)如果S合法,则(S).[S]合法 (3)如果A.B合法,则AB合法 思路: 设dp[i][j]为s(i,j)变为合法串后,合法串的长度或需要添加的字符的个数,状态转移: (1)如果s[i]和s[j]匹配,dp[i,j]=dp[i+1,j-1]. (2)如果不匹配,划分s(i,j)为s(i,k)和s(k+1,j),划分后dp[i,j]=dp[i,k]+dp[