最短路问题之Dijkstra算法

题目:

  在上一篇博客的基础上,这是另一种方法求最短路径的问题。

  Dijkstra(迪杰斯特拉)算法:找到最短距离已经确定的点,从它出发更新相邻顶点的最短距离。此后不再关心前面已经确定的“最短距离已经确定的点”。

  Dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。

  初始时,集合T只有顶点s。然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,OK,此时完成一个顶点,然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。

代码:

  1 import java.util.HashSet;
  2 import java.util.Set;
  3
  4 public class 图的最短路问题_Dijkstra {
  5     public static void main(String[] args) {
  6         int s = 1;
  7         int[] shortestPath = shortestPath(s);
  8
  9         for (int i = 0; i < prev.length; i++) {
 10             System.out.println((char) (‘A‘ + s) + "到" + (char) (‘A‘ + i) + "的路径");
 11             System.out.print((char) (‘A‘ + i) + "<-");
 12             int j = prev[i];
 13             while (j != s) {
 14                 System.out.print((char) (‘A‘ + j) + "<-");
 15                 j = prev[j];
 16             }
 17             System.out.print((char) (‘A‘ + j));
 18             System.out.println(":" + shortestPath[i]);
 19         }
 20     }
 21
 22     static int[] prev;
 23
 24     /**
 25      * 求起点到各顶点的最短距离
 26      *
 27      * @param s 起点
 28      * @return
 29      */
 30     private static int[] shortestPath(int s) {
 31         // 顶点个数
 32         int n = graph.length;
 33         // 记录每个点的前驱
 34         prev = new int[n];
 35         // 一定要初始化,源点的前驱是自身
 36         prev[s] = s;
 37         // 记录s到各顶点的最短距离
 38         int[] d = new int[n];
 39         d[s] = 0;// 自己到自己的距离为0
 40         // 记录已经找到最短距离的顶点
 41         Set<Integer> T = new HashSet<>();
 42         T.add(s);
 43
 44         /*-第一步:直接可达的顶点,用距离来初始化d,d[s]=0,可直达的把距离记录下来作为待定值-*/
 45         for (int i = 0; i < n; i++) {
 46             if (i != s && graph[s][i] == 0)
 47                 d[i] = Integer.MAX_VALUE;// 不可直达的顶点,先以最大整数作为待定值
 48             if (i != s && graph[s][i] > 0) {
 49                 d[i] = graph[s][i]; // 可直达的顶点,以直达距离作为待定值
 50                 prev[i] = s; // 可直达的顶点,其前驱是源点
 51             }
 52         }
 53         // Util.print(d);
 54
 55         while (T.size() < n) {
 56             /*-第二步:从待定的距离表中找到最小值,这个值可以作为确定值,为什么?-*/
 57             int min = minIndex(d, T);
 58             T.add(min);
 59             if (T.size() == n)
 60                 break;
 61             /*-第三步,看这个新确定的顶点的出度,看看从源点出发是经过这个顶点到其邻居近还是直达更近,如果更近就要更新-*/
 62             // 扫描index的邻居
 63             for (int neighbor = 0; neighbor < n; neighbor++) {
 64                 int cost = graph[min][neighbor];
 65                 // 更新
 66                 if (cost > 0 && d[neighbor] > d[min] + cost) {
 67                     d[neighbor] = d[min] + cost;
 68                     prev[neighbor] = min; // 更新最短路后,要更新i这个点的前驱
 69                 }
 70             }
 71         }
 72         return d;
 73     }
 74
 75     /**
 76      * 从未确定的点里面找一个最小的
 77      *
 78      * @param d
 79      * @param t 已确定了最短距离的顶点集
 80      * @return
 81      */
 82     private static int minIndex(int[] d, Set<Integer> t) {
 83         int index = -1;
 84         int min = Integer.MAX_VALUE;
 85         for (int i = 0; i < d.length; i++) {
 86             if (!t.contains(i) && d[i] < min) {
 87                 min = d[i];
 88                 index = i;
 89             }
 90         }
 91         return index;
 92     }
 93
 94     static int[][] graph = {
 95             { 0, 2, 5, 0, 0, 0, 0 },
 96             { 2, 0, 4, 6, 10, 0, 0 },
 97             { 5, 4, 0, 2, 0, 0, 0 },
 98             { 0, 6, 2, 0, 0, 1, 0 },
 99             { 0, 10, 0, 0, 0, 3, 5 },
100             { 0, 0, 0, 1, 3, 0, 9 },
101             { 0, 0, 0, 0, 5, 9, 0 }
102             };
103 }

结果:

  

  例题,POJ-1502

原文地址:https://www.cnblogs.com/xiaoyh/p/10416000.html

时间: 2024-08-29 03:03:39

最短路问题之Dijkstra算法的相关文章

图与网络模型及方法之最短路问题(dijkstra算法)

两个指定顶点之间的最短路径: 两个指定顶点之间最短路问题的数学规划模型: 每对顶点之间的最短路径: 最小生成树问题: Prim算法: Prim算法类似病毒感染的过程,其中P中存放的是已经计算出的顶点(即前一顶点与后一顶点构成的边在最短路径上),然后遍历P中所有的顶点,找出与V-P中所构成的边的最小值得那个顶点a,然后将顶点a归入P中,如此迭代,最终P=V,即算出了最小生成数. Kruskal算法: 其实Kruskal算法的思想和Prim算法的思想都是一样的(都是将所有点分为两个集合,已经遍历过的

P103 Dijkstra算法 单源最短路问题优化算法

///标准的dijkstra算法 void dijkstra() { while(true) { int vert=-1; dis[-1]=INF; for(int i=0;i<num_v;i++) { if( (!used[i]) && ( vert==-1||dis[i]<dis[vert] ) ) {vert=i;} } if(vert==-1) break;///这里要提前break;好像是这样... used[vert]=1; for(int i=0;i<num

Dijkstra算法(求解单源最短路)详解 + 变形 之 poj 1860 Currency Exchange

/* 求解单源最短路问题:Dijkstra算法(该图所有边的权值非负) 关键(贪心): (1)找到最短距离已经确定的节点,从它出发更新与其相邻节点的最短距离: (2)此后不再关心(1)中“最短距离已经确定的节点”. 时间复杂度(大概的分析,不准确): “找到最短距离已经确定的节点” => O(|V|) "从它出发更新与其相邻节点的最短距离" => 邻接矩阵:O(|V|),邻接表:O(|E|) 需要循环以上两个步骤V次,所以时间复杂度:O(V^2) 即:在|E|较小的情况下,

7-9 旅游规划 (25 分)(Dijkstra算法)

题意: ? 思路:单源最短路问题,Dijkstra算法搞定就可以了,因为要找出最便宜的最短路,所以需要在更新最短距离的时候加一个条件(即当最短距离相等的时候,如果该路径的花费更小,就更新最小花费)就可以了.之前自己学的最短路的水平也就仅限于模板题的水平,现在可以在条件上稍微加一些变化,做了数据结构的作业,顺便加深了自己对最短路(Dijkstra)算法的理解. 题目所给样例的示意图(数据放在了代码的后边): ? 代码:  1 #include <iostream> 2 #include <

最短路问题 Dijkstra算法- 路径还原

1 // 路径还原 2 // 求最短路,并输出最短路径 3 // 在单源最短路问题中我们很容易想到,既然有许多条最短路径,那将之都存储下来即可 4 // 但再想一下,我们是否要把所有的最短路径都求出来呢? 5 // 实际上不需要,这里我们用一个数组来记录最短路径,之后的最短路径都是在之前最短路径上的延申 6 // 所以只需要一个数组,存储前一个节点即可 7 8 // 这里我们用邻接表和优先级队列来实现复杂度为o( E*log(N) )的Dijkstra算法 9 10 #include <cstd

单源最短路问题 dijkstra算法 总结

Dijkstra(迪杰斯特拉)算法,用于计算一个节点到其他所有节点的最短路径.要注意的是这个算法中路径的权值不能有负边,如果有负边的话要运用bellman ford算法. 学习了一下dijkstra算法,感觉跟最小生成树的Prim算法有点类似.感觉dijkstra也是一个贪心的策略,用集合S表示的是已经找出最小路径的点,用dis[]来表示每个点当前距离源点的最短距离.再用一个数组来存储两点之间的距离,对于没有直接相连的两点就将值赋为INF. 1.一开始的时候,集合S中只有源点. 2.选取尚未被找

658 - It&#39;s not a Bug, it&#39;s a Feature! (Dijkstra算法)

今天第一次系统的学习了一下最短路算法,开始刷第十一章,第一次写Dijkstra算法,出现了很多喜闻乐见的错误..而且uva上样例很水,瓢虫也很水 ,坑了我好久. 首先是对于结点的处理,我们必须要维护一个二元组,一个表示结点一个表示当前结点最短路.   因为Dijkstra算法利用了优先队列来加速算法,所以需要定义小于运算符,一开始我直接将状态装进了优先队列,显然是不对的,因为优先队列的作用就是取出当前距离最短的结点. 其次,说说最短路算法蕴含的巧妙思想: 每次从当前所有还未标记的结点中选择一个距

最短路问题(Bellman/Dijkstra/Floyd)

最短路问题(Bellman/Dijkstra/Floyd) 寒假了,继续学习停滞了许久的算法.接着从图论开始看起,之前觉得超级难的最短路问题,经过两天的苦读,终于算是有所收获.把自己的理解记录下来,可以加深印象,并且以后再忘了的时候可以再看.最短路问题在程序竞赛中是经常出现的内容,解决单源最短路经问题的有bellman-ford和dijkstra两种算法,其中,dijikstra算法是对bellman的改进.解决任意两点间的最短路有Floyd-warshall算法. 单源最短路1(bellman

【Dijkstra算法】Roadblocks

Time Limit: 2000MS   Memory Limit: 65536K       Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along th