单源最短路径(Dijkstra)算法
2016-08-20 10:27
477 查看
Dijkstra 算法是一种贪心算法。
假定源点为 u,顶点集合 V 被划分为两部分:S 和 V-S,其中 S中的顶点到源点的最短路径的长度已经确定,V-S中的顶点到源点的最短路径待定。
思想:
1. 每次从 V-S 中选择一个距离 源点最近的顶点,将其加入到 S 中,并从 V-S 中删除这个顶点;
2. 因为 S 中加入了新的顶点,更新 V-S 中其他所有点顶到源点的距离;
3. 当 V-S 为空时算法结束。
C++ 代码
输入样例对应的输出结果:
假定源点为 u,顶点集合 V 被划分为两部分:S 和 V-S,其中 S中的顶点到源点的最短路径的长度已经确定,V-S中的顶点到源点的最短路径待定。
思想:
1. 每次从 V-S 中选择一个距离 源点最近的顶点,将其加入到 S 中,并从 V-S 中删除这个顶点;
2. 因为 S 中加入了新的顶点,更新 V-S 中其他所有点顶到源点的距离;
3. 当 V-S 为空时算法结束。
C++ 代码
#include <iostream> #include <limits> #include <vector> using namespace std; const int INFINITE = numeric_limits<int>::max(); /* n:顶点个数(从 1 开始计数) * u:源点 * C:带权邻接矩阵 * dist:记录某顶点与源点 u 的最短路径长度 * p:记录某顶点到源点的最短路径上的该顶点的前驱顶点 */ void Dijkstra(int n, int u, float *dist, int *p, int **C) { bool s ;// 用于标记顶点是否加入了 S for(int i=1; i <= n; i++) { s[i] = false;// 处源点外,所有顶点都还未加入 S,在 V-S 中 dist[i] = C[u][i];// 初始化所有其他顶点到源点的距离 // 初始化所有其他顶点到源点的前驱 if(INFINITE == dist[i]) { p[i] = -1; } else { p[i] = u; } } s[u] = true;// 源点 u 默认加入 S dist[u] = 0;// 源点 u 到自己的距离为 0 for(int i=1; i <= n; i++) {// 遍历所有其他顶点 int minDist = INFINITE; int t = u; for(int j=1; j <= n; j++) {// 在 V-S 中寻找距离源点最近的点 t if(!s[j] && (dist[j]<minDist)) { t = j; minDist = dist[j]; } } if(t == u)// 表示剩余的顶点要么到源点不可达,要么已经全部找到了最短距离都加入到 S 了。 break; s[t] = true;// 找到这个顶点后,将其加入到 S for(int j=1; j <= n; j++) {// 因为有新的顶点加入到 S,故更新其他所有未加入的顶点(V-S中的顶点)到源点的距离和前驱 if(!s[j] && C[t][j]<INFINITE) if(dist[j] > (dist[t]+C[t][j])) { dist[j] = dist[t]+C[t][j]; p[j] = t; } } } } int** getMatC(int n, int m) {// 输入顶点个数,边个数,得到有向带权邻接矩阵 int **C = new int*[n+1]; for(int i=0; i <= n; i++) { C[i] = new int[n+1](); for(int j=0; j <= n; j++) if(i != j) C[i][j] = INFINITE; } for(int i=1; i <= m; i++) { int x, y; int distance = 0; cin >> x >> y >> distance; if(1 <= x && x <= n && 1 <= y && y <= n) C[x][y] = distance; } return C; // 输入样例:(有向带权图) // | 1 2 3 4 5 //--------------------- // 1 | 0 8 32 ∞ ∞ // 2 | 12 0 16 15 ∞ // 3 | ∞ 29 0 ∞ 13 // 4 | ∞ 21 ∞ 0 7 // 5 | ∞ ∞ 27 19 0 /* 即: 5 11 1 1 2 8 1 3 32 2 1 12 2 3 16 2 4 15 3 2 29 3 5 13 4 2 21 4 5 7 5 3 27 5 4 19 */ } vector<int> getPath(int* p, int u, const int& v) { vector<int> path; path.push_back(v); int s = p[v]; while(s != u) { path.push_back(s); s = p[s]; } path.push_back(s); return path; } void printVec1D(const vector<int>& vec) { if(!vec.empty()) { for(int i = vec.size()-1; i > 0; i--) cout << vec[i] << " -> "; cout << vec[0] << endl; } } int main() { int n/*顶点数*/, m/*边数*/, u/*源点*/; cin >> n >> m >> u; int **C = getMatC(n, m); if(NULL != C) { float dist[n+1];// 存放距离 int path[n+1];// 存放前驱 Dijkstra(n, u, dist, path, C); for(int i=1; i <= n; i++) { if(INFINITE != dist[i]) { if(i != u) { cout << "顶点 " << u << " 到顶点 " << i << " 的距离是: " << dist[i] << endl; cout << "路径为:"; printVec1D(getPath(path, u, i)); } } else cout << "顶点 " << u << " 到顶点 " << i << " 不可达!" << endl; } } return 0; }
输入样例对应的输出结果:
相关文章推荐
- 贪心算法之最小生成树prim与单源最短路径dijkstra
- 贪心算法——单源最短路径 dijkstra
- Dijkstra单源最短路径算法
- 单源最短路径(1):Dijkstra 算法
- 贪心算法之单源最短路径Dijkstra
- 贪心算法 - 单源最短路径 Dijkstra
- 【经典算法】Dijkstra单源最短路径算法
- Dijkstra 单源最短路径算法
- Dijkstra算法求单源最短路径(二)(BFS的改版)
- [算法导论] 单源最短路径 - Dijkstra 学习笔记
- 关于图的常用算法——Dijkstra单源最短路径、Floyd多源最短路径、Prim和Kruskal最小生成树算法
- 数据结构与算法--单源最短路径算法之dijkstra
- Dijkstra单源最短路径算法
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路)Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- Dijkstra算法求解单源最短路径
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- POJ 1847 Tram(Dijkstra单源有向图最短路径算法)
- Dijkstra算法求单源最短路径
- 单源最短路径的Dijkstra 算法
- 迪杰斯特拉(Dijkstra)算法求解单源最短路径及其相应长度(java实现)