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

  1 // 路径还原
  2 // 求最短路,并输出最短路径
  3 // 在单源最短路问题中我们很容易想到,既然有许多条最短路径,那将之都存储下来即可
  4 // 但再想一下,我们是否要把所有的最短路径都求出来呢?
  5 // 实际上不需要,这里我们用一个数组来记录最短路径,之后的最短路径都是在之前最短路径上的延申
  6 // 所以只需要一个数组,存储前一个节点即可
  7
  8 // 这里我们用邻接表和优先级队列来实现复杂度为o( E*log(N) )的Dijkstra算法
  9
 10 #include <cstdio>
 11 #include <iostream>
 12 #include <queue>
 13 #include <vector>
 14
 15 using namespace std;
 16
 17 const int max_N = 1000+2;
 18 const int max_E = 10000+2;
 19 const int INF = 1e9;
 20
 21 int N,E,S;
 22 int d[max_N];
 23 int pre[max_N];
 24
 25 struct edge
 26 {
 27     int to,cost;
 28 };
 29 edge es[max_N];
 30
 31 vector<edge> G[max_N];
 32
 33 typedef pair<int,int> P;
 34
 35 void Dijkstra(int s)
 36 {
 37     pre[s]=-1;
 38     fill(d,d+N,INF);
 39     d[s]=0;
 40     // 实现最小堆
 41     priority_queue< P,vector<P>,greater<P> > que;
 42     que.push(P(0,s));
 43
 44     while(!que.empty())
 45     {
 46         // 非空时,取出一个顶点
 47         P p=que.top();
 48         que.pop();
 49         // 当前节点的编号是v,队列中记录的到当前节点的最短距离是p.first
 50         int v=p.second;
 51         // 如果当前节点的最小值,小于数组中记录的最小值的话
 52         // 说明当前节点的最小值已经被覆盖过了,这个节点是无效节点,继续下一次循环
 53         if(d[v]<p.first)
 54         {
 55             continue;
 56         }
 57
 58         for(int i=0;i<G[v].size();++i)
 59         {
 60             edge e=G[v][i];
 61
 62             if(d[e.to]>d[v] + e.cost)
 63             {
 64                 d[e.to]=d[v]+e.cost;
 65                 pre[e.to]=v;
 66                 que.push(P( d[e.to],e.to ));
 67             }
 68         }
 69
 70     }
 71
 72 }
 73
 74 void path(int i)
 75 {
 76     if(i==S)
 77     {
 78         printf("start:%d\n",S);
 79         return;
 80     }
 81     vector<int> p;
 82     for(;i!=-1;i=pre[i])
 83     {
 84         p.push_back(i);
 85     }
 86     vector<int>::iterator it;
 87     for(it=p.end()-1;it!=p.begin()-1;--it)
 88     {
 89         cout<<*it<<‘ ‘;
 90     }
 91     cout<<endl;
 92 }
 93
 94 int main()
 95 {
 96     scanf("%d %d",&N,&E);
 97     int a,b,c;
 98     for(int i=0;i<E;++i)
 99     {
100         scanf("%d %d %d",&a,&b,&c);
101         edge e;
102         e.to=b;
103         e.cost=c;
104         G[a].push_back(e);
105         // 无向图
106         e.to=a;
107         e.cost=c;
108         G[b].push_back(e);
109     }
110     // 起点为0号节点
111     S=0;
112
113     Dijkstra(S);
114
115     for(int i=0;i<N;++i)
116     {
117         printf("%d ",d[i]);
118     }
119
120     printf("\n\n");
121
122     for(int i=0;i<N;++i)
123     {
124         path(i);
125     }
126
127     return 0;
128 }
129
130 /*
131 7 10
132 0 1 2
133 0 2 5
134 1 2 4
135 1 3 6
136 1 4 10
137 2 3 2
138 3 5 1
139 4 5 3
140 4 6 5
141 5 6 9
142
143 */

原文地址:https://www.cnblogs.com/jishuren/p/12318415.html

时间: 2024-07-31 06:14:59

最短路问题 Dijkstra算法- 路径还原的相关文章

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

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

HDU - 2680 - Choose the best route (经典最短路问题dijkstra算法!!)

Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7671    Accepted Submission(s): 2524 Problem Description One day , Kiki wants to visit one of her friends. As she is liable

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

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][

最短路问题之Dijkstra算法

题目: 在上一篇博客的基础上,这是另一种方法求最短路径的问题. Dijkstra(迪杰斯特拉)算法:找到最短距离已经确定的点,从它出发更新相邻顶点的最短距离.此后不再关心前面已经确定的“最短距离已经确定的点”. Dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0).若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同

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

POJ 3255 Roadblocks (次短路径 + Dijkstra算法)

Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7982   Accepted: 2921 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 q

Dijkstra算法(带路径模板)

个人心得:Dijkstra算法是贪心思想的一种延伸,注意路径pre,pre数组表示此时最短路径中的前一个顶点.每次更新到目的点时更新: 从源点出发,更新路径,然后找出此时最短的点,然后以这个点为头,看能否缩减路程, #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> usi

山东省第七届ACM竞赛 C题 Proxy (Dijkstra算法,单源路径最短问题)

题意:给定0-n+1个点,和m条边,让你找到一条从0到n+1的最短路,输出与0相连的结点... 析:很明显么,是Dijkstra算法,不过特殊的是要输出与0相连的边,所以我们倒着搜,也是从n+1找到0, 那么不就能找到与0相连的边么,注意判断相等值的时候.当时写错了好多次,就是没有考虑好边界. 代码如下: #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #

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

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