Dijkstra算法

一.最短路径的最优子结构性质

该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。下面证明该性质的正确性。

假设P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而 P(k,s)不是从k到s的最短距离,那么必定存在另一条从k到s的最短路径P'(k,s),那么 P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。则与P(i,j)是从i到j的最短路径相矛盾。因此该性质得证。

二.Dijkstra算法

由上述性质可知,如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点。那么(Vi...Vk)也必定是从i到k的最短 路径。为了求出最短路径,Dijkstra就提出了以最短路径长度递增,逐次生成最短路径的算法。譬如对于源顶点V0,首先选择其直接相邻的顶点中长度最 短的顶点Vi,那么当前已知可得从V0到达Vj顶点的最短距离dist[j]=min{dist[j],dist[i]+matrix[i][j]}。根 据这种思路,

假设存在G=<V,E>,源顶点为V0,U={V0},dist[i]记录V0到i的最短距离,path[i]记录从V0到i路径上的i前面的一个顶点。

1.从V-U中选择使dist[i]值最小的顶点i,将i加入到U中;

2.更新与i直接相邻顶点的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]})

3.知道U=V,停止。

三.算法实例

先给出一个无向图

用Dijkstra算法找出以A为起点的单源最短路径步骤如下

代码:

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4.  
  5. #define DEBUG 0
  6. #define INF 0x7fffffff
  7. #define MAX 20
  8.  
  9. int N, V;
  10. int graph[MAX][MAX];
  11. int dist[MAX];
  12. int prev[MAX];
  13. bool visited[MAX];
  14.  
  15. void PrintPath()
  16. {
  17. for( int i = ; i <= V; i++ )
  18. {
  19. cout << "1 --> " << i << " : " << dist[i] << endl;
  20. }
  21.  
  22. for( int i = ; i <= V; i++ ) //计算从1到每个顶点的距离
  23. {
  24. int path[MAX] = {};
  25. int step = ;
  26. int cur = i;
  27. do
  28. {
  29. path[step++] = cur;
  30. cur = prev[cur];
  31. }
  32. while( cur != - ); //前一个点为-1,则结束
  33.  
  34. for( int j = step - ; j >= ; j-- )
  35. {
  36. cout << path[j] << " ";
  37. }
  38. cout << endl;
  39. }
  40. }
  41.  
  42. int GetMinDist()
  43. {
  44. int index, min = INF;
  45. for( int i = ; i <= V; i++ )
  46. {
  47. if( !visited[i] && min > dist[i] )
  48. {
  49. min = dist[i];
  50. index = i;
  51. }
  52. }
  53. return index;
  54. }
  55.  
  56. void Dijkstra( int v )
  57. {
  58. for( int i = ; i <= V; i++ )
  59. {
  60. if( graph[v][i] == INF )
  61. {
  62. dist[i] = INF;
  63. prev[i] = -;
  64. }
  65. else
  66. {
  67. dist[i] = graph[v][i];
  68. prev[i] = v;
  69. }
  70. visited[i] = false;
  71. }
  72.  
  73. dist[v] = ;
  74. visited[v] = true;
  75.  
  76. for( int i = ; i < V; i++ ) //迭代V-1次,不用计算源点了,还剩下V-1个需要计算的顶点
  77. {
  78. int u = GetMinDist();
  79.  
  80. visited[u] = true;
  81.  
  82. for( int j = ; j <= V; j++ ) //更新dist数组
  83. {
  84. if( visited[j] == false && graph[u][j] != INF && dist[u] != INF && dist[j] > dist[u] + graph[u][j] )
  85. {
  86. dist[j] = dist[u] + graph[u][j];
  87. prev[j] = u;
  88. }
  89. }
  90. }
  91. }
  92.  
  93. void InitData()
  94. {
  95. memset( visited, false, sizeof( visited ) ); //初始化visited
  96.  
  97. for( int i = ; i <= V; i++ )
  98. {
  99. for( int j = ; j <= V; j++ )
  100. {
  101. graph[i][j] = INF;
  102. }
  103. dist[i] = INF;
  104. }
  105. }
  106.  
  107. int main()
  108. {
  109. int a, b, value;
  110. while( cin >> V, V ) // 输入顶点数
  111. {
  112. cin >> N; //输入边数
  113. InitData();
  114. for( int i = ; i <= N; i++ )
  115. {
  116. cin >> a >> b >> value;
  117. graph[a][b] = graph[b][a] = value;
  118. }
  119.  
  120. Dijkstra( );
  121. PrintPath();
  122. }
  123. }

输入文件:

  1. /*
  2.  
  3. 6 10
  4. 1 2 4
  5. 1 3 8
  6. 2 3 3
  7. 2 4 4
  8. 2 5 6
  9. 3 4 2
  10. 3 5 2
  11. 4 5 4
  12. 4 6 9
  13. 5 6 4
  14.  
  15. result :
  16. 1 --> 1 : 0
  17. 1 --> 2 : 4
  18. 1 --> 3 : 7
  19. 1 --> 4 : 8
  20. 1 --> 5 : 9
  21. 1 --> 6 : 13
  22. 1
  23. 1 2
  24. 1 2 3
  25. 1 2 4
  26. 1 2 3 5
  27. 1 2 3 5 6
  28.  
  29. */

Floyd算法

1.算法思想原理:

Floyd算法是一个经典的动态规划算法。从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,则设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

2.算法描述:

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

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

3.Floyd算法过程矩阵的计算----十字交叉法

方法:两条线,从左上角开始计算一直到右下角 如下所示

给出矩阵,其中矩阵A是邻接矩阵,而矩阵Path记录u,v两点之间最短路径所必须经过的点

相应计算方法如下:

最后A3即为所求结果.

算法实现:

  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. #define INF 65536
  6. #define MAX 20
  7.  
  8. int graph[MAX][MAX];
  9. int KeyPoint[MAX][MAX];
  10. int V, E;
  11.  
  12. void PrintPath()
  13. {
  14. cout << graph[][V] << endl;
  15.  
  16. int path[MAX];
  17. int step = ;
  18. int cur = V;
  19.  
  20. while(cur != ) {
  21. path[step++] = cur;
  22. cur = KeyPoint[][cur];
  23. }
  24.  
  25. path[step++] = ; //保存起点
  26.  
  27. for (int j = step - ; j >= ; j--)
  28. {
  29. cout << path[j] << " ";
  30. }
  31. cout << endl;
  32. }
  33.  
  34. void Floyd()
  35. {
  36. graph[][] = ;
  37.  
  38. for(int k = ; k <= V; k++) //对于每一个节点k,检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立
  39. for(int i = ; i <= V; i++)
  40. for(int j = ; j <= V; j++)
  41. if(graph[i][j] > graph[i][k] + graph[k][j])
  42. {
  43. graph[i][j] = graph[i][k] + graph[k][j];
  44. KeyPoint[i][j] = k;
  45. }
  46. PrintPath();
  47. }
  48.  
  49. void InitData()
  50. {
  51. for(int i = ; i <= V; i++)
  52. {
  53. for(int j = ; j <= V; j++)
  54. {
  55. graph[i][j] = INF;
  56. KeyPoint[i][j] = ;
  57. }
  58. }
  59. }
  60.  
  61. int main()
  62. {
  63. int a, b, length;
  64. while(cin >> V, V) //输入顶点数
  65. {
  66. InitData();
  67.  
  68. cin >> E; //输入边数
  69. for(int i = ; i <= E; i++)
  70. {
  71. cin >> a >> b >> length;
  72. graph[a][b] = graph[b][a] = length;
  73. }
  74.  
  75. Floyd();
  76. }
  77. }

测试用例

  1. /*
  2.  
  3. 6 10
  4. 1 2 4
  5. 1 3 8
  6. 2 3 3
  7. 2 4 4
  8. 2 5 6
  9. 3 4 2
  10. 3 5 2
  11. 4 5 4
  12. 4 6 9
  13. 5 6 4
  14.  
  15. result:
  16. 13
  17. 1 2 3 5 6
  18.  
  19. */

Algorithm --> Dijkstra和Floyd最短路径算法的更多相关文章

  1. Dijkstra 单源最短路径算法

    Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...

  2. Floyd最短路径算法

    看完这篇文章写的小程序,Floyd最短路径算法,求从一个点到另一个点的最短距离,中间可以经过其他任意个点.三个for循环,从i到j依次经过k的最短距离,最外层for循环是经过点K,内部两个循环是从i( ...

  3. Dijkstra单源点最短路径算法

    学习参考: Dijkstra算法(单源最短路径) 最短路径—Dijkstra算法和Floyd算法 使用的图结构: 邻接矩阵: -1 20 -1 25 80-1 -1 40 -1 -1-1 -1 -1 ...

  4. Floyd最短路径算法(来自微信公众号“算法爱好者”改编)

    暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有4个城市8条公路,公路上的数字表 ...

  5. 【模板 && 拓扑】 Dijkstra 单源最短路径算法

    话不多说上代码 链式前向星233 #include<bits/stdc++.h> using namespace std; ,_max=0x3fffffff; //链式前向星 struct ...

  6. 图之单源Dijkstra算法、带负权值最短路径算法

    1.图类基本组成 存储在邻接表中的基本项 /** * Represents an edge in the graph * */ class Edge implements Comparable< ...

  7. 一篇文章讲透Dijkstra最短路径算法

    Dijkstra是典型最短路径算法,计算一个起始节点到路径中其他所有节点的最短路径的算法和思想.在一些专业课程中如数据结构,图论,运筹学等都有介绍.其思想是一种基础的求最短路径的算法,通过基础思想的变 ...

  8. Johnson 全源最短路径算法

    解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...

  9. Floyd-Warshall 全源最短路径算法

    Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...

随机推荐

  1. Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.RequestContext

    1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...

  2. ORA-00904:"T1"."AREA_ID" :标识符无效

    1.错误描述 ORA-00904:"T1"."AREA_ID" :标识符无效 00904 . 00000 - "%s:invalid identifi ...

  3. pat1101-1110

    1101 #include<cmath> #include<map> #include<iostream> #include<cstring> #inc ...

  4. trs.getElementsByTagName is not a function 出现原因及解决办法

    好久没有操作dom元素了,在定义dom元素时, let tBo = document.getElementById('tBody') let trs = tBo.getElementsByTagNam ...

  5. Windows Developer Day Review

    北京时间 3 月 8 日凌晨 1 点钟,今年的第一次 Windows Developer Day 正式召开.    因为时间太晚看不了直播,我也是第二天早上在公司看的重播.整个会议过程有很多值得去研究 ...

  6. 微信小程序滚动动画,点击事件及评分星星制作!

    前言 小程序上线刷爆了朋友圈,但是最近渐渐消沉了,很少有动静!最近公司项目需要,体验了一下微信小程序,制作了几个功能,布局感觉很简单,但是交互和动画等写起来确实很费劲,主要是因为他不能操作DOM,只能 ...

  7. CentOS7使用dnf安装mysql

    1.安装mysql的yum仓库 执行以下命令: yum localinstall https://dev.mysql.com/get/mysql57-community-release-el7-11. ...

  8. DirectSound---3D环境

    DirectSound对于单声道的Wav文件(或者说对于单声道的PCM音频数据)提供了内置3D音效的模拟,你能够控制每一个声源和收听者的立体位置,对移动的物体应用多普勒效果等等.在单个应用程序中,可以 ...

  9. 快速开发 HTML5 WebGL 的 3D 斜面拖拽生成模型

    前言 3D 场景中的面不只有水平面这一个,空间是由无数个面组成的,所以我们有可能会在任意一个面上放置物体,而空间中的面如何确定呢?我们知道,空间中的面可以由一个点和一条法线组成.这个 Demo 左侧为 ...

  10. kerberos下JAVA代码操作hbase的方式(客户端方式,应用程序方式)

    (一)如果部署JAVA 代码的主机用户获取了kerberos权限情况下 假设主机名是:client su - client 登录主机后 kinit -kt /keytab的路径/client.keyt ...