利用Dijkstra算法实现记录每个结点的所有最短路径
最近在做PAT时发现图论的一些题目需要对多条最短路径进行筛选,一个直接的解决办法是在发现最短路径的时候就进行判断,选出是否更换路径;另一个通用的方法是先把所有的最短路径记录下来,然后逐个判断。前者具有一定的难度并且不好排查BUG,因此我设计了一种基于Dijkstra的记录所有最短路的简捷算法,用于解决此类题目。
我们知道,Dijkstra是解决单源最短路问题的,并且最基本的算法仅能求出最短路的长度,而不能输出路径,本文基于Dinjkstra进行改进,使之能记录源点到任意点的所有最短路径。
使用vector<int>来记录一条路径,因为每个结点可能有多条最短路径,因此把这些路径都装在一个vector中,因此可以用一个vector<vector<int> >来表示一个结点的所有最短路径,把所有结点的最短路径都存放起来,又需要一个vector容器,因此所有结点的所有最短路径的集合可以用vector<vector<vector<int>
> >来表示。
约定:结点编号为0到N-1,源点为0,到每个点的最短距离存储在数组minD[N]中。
在Dijkstra算法初始化时,找出所有源点的邻接点w并且把相应的最短距离minD[w]更新,同时初始化这些点w的第一条最短路径0->w(实现方法为分别push_back 0和w)。接下来将会找到一个到源点最短的点v,并且把v并入集合,对v的所有未访问的邻接点,如果到达w的路径(0->...->w)在包含v之后(0->...->v->w)变短,则删除w之前所有的最短路径,并且更新为到v的所有最短路径加上w点(注意对每个到v的最短路径都要这样处理);如果到达w的路径在包含v之后长度不变,说明发现了一条新的最短路径,在w原来最短路径容器的基础上再压入一个新的最短路径,这条路径为所有到v的最短路径加上w点。
经过这样的运算,就可以得到所有结点的所有最短路径了,下面以一个实例对算法进行测试,并且附上源代码。
题目:求下图的源点0到所有结点的最短路径。
输入:
5 8
2 4 1
0 1 3
0 2 6
1 3 2
1 4 1
3 4 1
3 2 1
0 4 4
输出:
源码为:
- #include <iostream>
- #include <stdio.h>
- #include <vector>
- using namespace std;
- #define MAX 1001
- #define INF 99999999
- int G[MAX][MAX];
- int minD[MAX];
- int minDist;
- int finalSet[MAX];
- int main()
- {
- int N,M;
- int v1,v2;
- int len;
- cin >> N >> M;
- for(int i = 0; i < N; i++){
- finalSet[i] = 0;
- minD[i] = INF;
- for(int j = 0; j < N; j++)
- G[i][j] = INF;
- }
- for(int i = 0; i < M; i++){
- scanf("%d%d%d",&v1,&v2,&len);
- G[v1][v2] = G[v2][v1] = len;
- }
- vector<vector<vector<int> > > nodes(N);
- // 设0为源点,计算从0到所有点的所有最短路径
- finalSet[0] = 1;
- minD[0] = 0;
- // 首先把所有源点邻接点的最短距离初始化为源点到这些点的距离
- for(int i = 1; i < N; i++){
- if(G[0][i] != INF) {
- minD[i] = G[0][i];
- vector<vector<int> > minPaths;
- minPaths.clear();
- vector<int> pathList;
- pathList.clear();
- pathList.push_back(0);
- pathList.push_back(i);
- minPaths.push_back(pathList);
- nodes[i] = minPaths;
- }
- }
- // 从所有minD中找出最小的,并入集合S,重复N-1次(源点已经加入集合)
- for(int i = 1; i < N; i++){
- minDist = INF;
- int v = -1; // 记录到源点记录最小的结点
- for(int w = 1; w < N; w++){
- if(!finalSet[w] && minDist > minD[w]){
- minDist = minD[w];
- v = w;
- }
- }
- if(v == -1) break; // v = -1说明找不到点了,当图不连通时才会出现这种情况
- // 已经找到了到源点最近的点v,将其并入集合,并且考虑原来的最短距离0->...->W在加入了v之后有没有可能变短
- // 如果变短了,就更新为0->...>v->W
- finalSet[v] = 1;
- for(int w = 1; w < N; w++){
- if(!finalSet[w]){
- int newD = minDist + G[v][w];
- if(newD < minD[w]){
- minD[w] = newD;
- vector<vector<int> > minPathsV = nodes[v];
- vector<int> pathList;
- nodes[w].clear();
- for(int index = 0; index < minPathsV.size(); index++){
- pathList = minPathsV[index];
- pathList.push_back(w);
- nodes[w].push_back(pathList);
- }
- }else if(newD == minD[w]){
- vector<vector<int> > minPathsV = nodes[v];
- vector<int> pathList;
- for(int index = 0; index < minPathsV.size(); index++){
- pathList = minPathsV[index];
- pathList.push_back(w);
- nodes[w].push_back(pathList);
- }
- }
- }
- }
- }
- for(int i = 1; i < N; i++){
- cout << "------------" << endl;
- cout << "0 to "<< i << ":" << endl;
- cout << "The miniest distance:" << endl << minD[i] << endl;
- cout << "The possible paths:" << endl;
- vector<vector<int> >minPaths = nodes[i];
- int size = minPaths.size();
- vector<int> pathList;
- for(int j = 0; j < size; j++){
- pathList = minPaths[j];
- int pathSize = pathList.size();
- for(int k = 0; k < pathSize - 1; k++){
- cout << pathList[k] << "->";
- }
- cout << pathList[pathSize - 1] << endl;
- }
- }
- return 0;
- }
利用Dijkstra算法实现记录每个结点的所有最短路径的更多相关文章
- python利用dijkstra算法求解图中最短距离
利用dijkstra算法,来完成图中两个顶点间最短的距离,可以直接复制使用,只需要修改参数即可 def dijkstra_raw(edges, from_node, to_node): "& ...
- 利用dijkstra算法规划线路
# dijkstra# 1.在数据库内预先存放了北京市内最新的道路节点,选用优化了得dijkstra算法进行线路规划. 当输入起点和终点后,会计算出最短的路径.同时还能选择查看路径经过的道路节点 ...
- 非负权值有向图上的单源最短路径算法之Dijkstra算法
问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...
- UVA - 12661 Funny Car Racing (Dijkstra算法)
题目: 思路: 把时间当做距离利用Dijkstra算法来做这个题. 前提:该结点e.c<=e.a,k = d[v]%(e.a+e.b); 当车在这个点的1处时,如果在第一个a这段时间内能够通过且 ...
- 单源最短路径—Bellman-Ford和Dijkstra算法
Bellman-Ford算法:通过对边进行松弛操作来渐近地降低从源结点s到每个结点v的最短路径的估计值v.d,直到该估计值与实际的最短路径权重相同时为止.该算法主要是基于下面的定理: 设G=(V,E) ...
- Dijkstra算法(迪杰斯塔拉算法)
算法描述: Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最 ...
- Dijkstra算法模拟讲解
dijkstra算法,是一个求单源最短路径算法 其算法的特点为: 层层逼进,有点类似宽度搜索的感觉 其需要的数据结构为: int map[N][N] 所有点之间的权表 ...
- 单源最短路径算法——Dijkstra算法(迪杰斯特拉算法)
一 综述 Dijkstra算法(迪杰斯特拉算法)主要是用于求解有向图中单源最短路径问题.其本质是基于贪心策略的(具体见下文).其基本原理如下: (1)初始化:集合vertex_set初始为{sourc ...
- pta7-7旅游规划(dijkstra算法)
题目链接:https://pintia.cn/problem-sets/1101307589335527424/problems/1101314114762387456 题意:给n给城市,m条公路,公 ...
随机推荐
- setTimeout、setInterval被遗忘的第三个参数
一.最近在看promise,惊奇的发现:原来 setTimeout不只有两个参数,我还能说什么呢?赶紧探探究竟. function multiply(input) { return new Promi ...
- 关于html+ashx开发中几个问题的解决方法
在跟html+ashx打交道的园友们肯定会发现,这种模式虽然优美,但在开发中会遇到一些难处理的地方.我也不例外,下面是自己在实际开发中总结出来的几条经验,希望跟大家分享,更希望得到大家的建议和更好的解 ...
- Rstudio-server 重新登录载入session的问题
Rstudio-server 非常好用,但是免费版的也有一些问题,一个是只能支持在一个客户端的登录,另一个就是每次登录都要导入之前session的问题,对于第二个问题的解决方案,我们可以进入到~/.r ...
- Jmeter(二)_基础元件
测试计划(Test Plan) 它用来描述一个测试方案,包含与本次性能测试所有相关的功能.也就说本次测试的所有内容是于基于一个计划的. "函数测试模式"复选框,如果被选择,它会使J ...
- 从输入url到页面返回到底发生了什么
1. 前言 Google应该是开发者平日里用得最多的网站之一,今早笔者在浏览器地址栏里键入www.google.com的时候,突然想了解下这背后的网络通信过程究竟是怎么样的.毕竟自己也算是一名Web开 ...
- 《读书报告 -- Elasticsearch入门 》-- 安装以及简单使用(1)
<读书报告 – Elasticsearch入门 > 第一章 Elasticsearch入门 Elasticsearch是一个实时的分布式搜索和分析引擎,使得人们可以在一定规模上和一定速度上 ...
- OpenCV+VS2013 属性表配置
简介 计算机视觉任务越来越多的依赖著名的开源计算机视觉库OpenCV.OpenCV 2.0 包含了一系列精心设计数据结构和经过优化的视觉算法,大家可以短时间内开发一个不错的视觉应用.OpenCV支持多 ...
- 一个貌似比较吊的递归转换为loop--总算成功了.--第二弹
前段时间用类似于散弹式编程的方式,各种猜测-运行验证-修正结果,最终成功转换了一个看起来比较有难度的递归函数.但总觉得很蛋疼,原因如下: 1.虽然正确,但是逻辑搞得比较复杂.现在去看,一头雾水,不知道 ...
- 一个貌似比较吊的递归转换为loop--总算成功了.
class Stack(object): """ A class to hold arguements and state data. """ ...
- 亲密接触Redis-第一天
引言 nosql,大规模分布式缓存遍天下,Internet的时代在中国由其走得前沿,这一切归功于我国特色的电商.因此nosql.大数据技术在中国应用的比国外还要前沿.从这一章开始我们将开始进入到真正的 ...