任意两点间最短路问题及路径还原

1Floyd-Warshall算法

考虑用动态规划的方法,只使用顶点0~k和i,j的情况下,记i到j的最短路径为d[k][i][j]。当k=0时,只考虑i和j,即d[0][i][j]=cost[i][j].然后我们就开始讨论从k到k+1是怎样变化的。

对于顶点0~k的i到j的最短路,如果这条路径不经过第k个顶点,那么d[k][i][j]=d[k-1][i][j]。当经过第k个顶点时,d[k][i][j]=d[k-1][i][k]+d[k-1][k][j](分成两短),这样总的递推式即为d[k][i][j]=min(d[k-1][i][j]+d[k-1][i][k]+d[k-1][k][j]).

由于是三维数组,每层都要遍历所有节点,所以复杂度为O(|V|^3)。

代码如下

int d[MAX_V][dMAX_V];
int V;
void warshall_floyd{
 for(int k=0;k<V;k++
   for(int i=0;i<V;i++)
    for(int j=0;j,V;j++)
   d[i][j]=min(d[i][j],d[i][k]+d[k][j]);//二维数组不断更新即可满足递推式
 }

2路径还原

本文和上篇博客讨论了如何求最短路径,但未能还原出最短路径是怎么走的。

思路如下:我们需要找到满足d[j]=d[k]+cost[k][j]的顶点k,他是最短路上j前面的点,不断寻找就能找到最短路,时间复杂度为O(|E|)。

如果我们用一个数组记录这个点prev[j]=k,那么时间复杂度就变为O(|V|)。

给出Dijkstra算法的代码作为参考:

int cost[MAX_V][MAX_E]
int d[MAX_V];
bool used[MAX_V];
int V;
int prev[MAX_V];
void dijkstra(int s){
  fill(d,d+V,INF);
  fill(used,used+V,false);
  d[s]=0;
  while(true){
  int v=-1;
  for(int u=0;u<V;u++){  //从未使用的顶点中选择一个距离最小的顶点(while的第一次循环选择的是点s)
   if(!used[u]&&(v==-1||d[u]<d[v]))
     v=u;
   }
 if (v==-1) break;
  used[v]=true;
  for(int u=0;u<V;u++){
    if(d[u]>d[v]+cost[v][u]){
   d[u]=d[v]+cost[v][u]; //更新和确定的点相连的点的距离
   prev[u]=v;  //记录前面的点
    }
   }
  }
}
//恢复最短路径
vector<int> get_path(int t){
  vector<int> path;
   for(;t!=-1;t=prev[t])
     path.push_back(t);
    reverse(path.begin(),path.end());  //翻转
   return path;
}
时间: 2024-10-12 14:36:33

任意两点间最短路问题及路径还原的相关文章

图论之最短路02-2——改进的任意两点间最短距离及路径

======================================================== 重要程度 ***** 求任意两点间最短距离及其路径.(万能最短路) 输入:权值矩阵,起点,终点 输出:最短距离矩阵,指定起讫点路径(经过的顶点编号) ======================================================== function renyizuiduanlu(W) clc disp('                        

图论之最短路02-1——任意两点间最短距离及路径

======================================================== 求任意两点间最短距离及其路径.(万能最短路) 输入:权值矩阵,起点,终点 输出:最短距离矩阵,指定起讫点路径(经过的顶点编号) 为任意一点到其他点最短路奠定基础 ======================================================== function [P d]=liangdianzuiduanlu(W,qidian,zhongdian) W

任意两点间的最短路问题 Floyd-Warshall算法

这一算法与之前的Bellman-F=Ford算法一样,都可以判断负环 只需要检查dp [i] [j] 是负数的顶点i即可 1 // 求解任意两点间的最短路径问题 2 // Floyed-Warshall算法 3 // 复杂度O(N^3),N为顶点数 4 5 #include <cstdio> 6 #include <iostream> 7 8 using namespace std; 9 // 用dp的思路来求解 10 // dp[k][i][j]:从i到j,只利用前K个节点的最短

Floyd-Warshall算法(求解任意两点间的最短路) 详解 + 变形 之 poj 2253 Frogger

/* 好久没有做有关图论的题了,复习一下. --------------------------------------------------------- 任意两点间的最短路(Floyd-Warshall算法) 动态规划: dp[k][i][j] := 节点i可以通过编号1,2...k的节点到达j节点的最短路径. 使用1,2...k的节点,可以分为以下两种情况来讨论: (1)i到j的最短路正好经过节点k一次 dp[k-1][i][k] + dp[k-1][k][j] (2)i到j的最短路完全

基于pgrouting的任意两点间的最短路径查询函数

前面文章介绍了如何利用postgresql创建空间数据库,建立空间索引和进行路径规划.但是在真实的场景中用户进行路径规划的时候都是基于经纬度数据进行路径规划的,因为用户根本不会知道道路上节点的ID.因此文本讲述如何查询任意两点间的最短路径. 一.定义函数名及函数参数 函数名定义为: pgr_fromAtoB 参数设置分别为: 输入为数据库表名,起点和终点的经纬度坐标 输出为:路段序号,gid号,道路名,消耗及道路集合体. IN tbl varchar, --数据库表名 IN x1 double

图论03—随意两点间最短距离及路径(改进)

======================================================== 重要程度 ***** 求随意两点间最短距离及其路径.(万能最短路) 输入:权值矩阵,起点,终点 输出:最短距离矩阵.指定起讫点路径(经过的顶点编号) ======================================================== function renyizuiduanlu(W) clc disp('                        

基于pgrouting的任意两点间的最短路径查询函数二

在前面的博文中写过一篇查询任意两点间最短路径的函数,当时对pgrouting不熟悉,功能很low.现在对该函数进行扩展,支持用户自己输入查询的数据库表,这一点看似简单,其实意义很大,在做室内导航的时候当用户所在的楼层变化的时候最短路径函数查询的数据表名称也会发生变化,不可能一栋大楼里的道路都是一样的吧,另外进行跨楼层的最短路径规划时,需要查询从A到楼梯口的最短路径和楼梯口到B的最短路径,这些都需要进行最短路径规划的时候能够自己选择数据表. DROP FUNCTION pgr_fromAtoB(t

任意两点间的最短路 Floyd及其本质

我们知道在已知起点的情况下,求到其他任何一点的最短路是用dijkstra,那么在一个有向图中,我们想知道任意两点之间的最短路,我们就可以使用floyd,而且这个算法表面看起来非常的简单,就是一个三重循环,如果这个图有N个点,那么复杂度为O(|N|3),代码如下. 1 for(int k=0;k<n;k++) 2 for(int i=0;i<n;i++) 3 for(int j=0;j<n;j++) 4 d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 在复杂度这

任意两点间最短距离floyd-warshall ---- POJ 2139 Six Degrees of Cowvin Bacon

floyd-warshall算法 通过dp思想 求任意两点之间最短距离 重复利用数组实现方式dist[i][j] i - j的最短距离 for(int k = 1; k <= N; k++) for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]); 非常好实现 O(V^3) 这里贴一道刚好用到的题 http://poj.org