最近在做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算法实现记录每个结点的所有最短路径的更多相关文章

  1. python利用dijkstra算法求解图中最短距离

    利用dijkstra算法,来完成图中两个顶点间最短的距离,可以直接复制使用,只需要修改参数即可 def dijkstra_raw(edges, from_node, to_node): "& ...

  2. 利用dijkstra算法规划线路

    # dijkstra# 1.在数据库内预先存放了北京市内最新的道路节点,选用优化了得dijkstra算法进行线路规划.    当输入起点和终点后,会计算出最短的路径.同时还能选择查看路径经过的道路节点 ...

  3. 非负权值有向图上的单源最短路径算法之Dijkstra算法

    问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...

  4. UVA - 12661 Funny Car Racing (Dijkstra算法)

    题目: 思路: 把时间当做距离利用Dijkstra算法来做这个题. 前提:该结点e.c<=e.a,k = d[v]%(e.a+e.b); 当车在这个点的1处时,如果在第一个a这段时间内能够通过且 ...

  5. 单源最短路径—Bellman-Ford和Dijkstra算法

    Bellman-Ford算法:通过对边进行松弛操作来渐近地降低从源结点s到每个结点v的最短路径的估计值v.d,直到该估计值与实际的最短路径权重相同时为止.该算法主要是基于下面的定理: 设G=(V,E) ...

  6. Dijkstra算法(迪杰斯塔拉算法)

    算法描述: Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最 ...

  7. Dijkstra算法模拟讲解

    dijkstra算法,是一个求单源最短路径算法 其算法的特点为: 层层逼进,有点类似宽度搜索的感觉 其需要的数据结构为:                  int map[N][N] 所有点之间的权表 ...

  8. 单源最短路径算法——Dijkstra算法(迪杰斯特拉算法)

    一 综述 Dijkstra算法(迪杰斯特拉算法)主要是用于求解有向图中单源最短路径问题.其本质是基于贪心策略的(具体见下文).其基本原理如下: (1)初始化:集合vertex_set初始为{sourc ...

  9. pta7-7旅游规划(dijkstra算法)

    题目链接:https://pintia.cn/problem-sets/1101307589335527424/problems/1101314114762387456 题意:给n给城市,m条公路,公 ...

随机推荐

  1. MySQL Innodb如何找出阻塞事务源头SQL

    在MySQL数据库中出现了阻塞问题,如何快速查找定位问题根源?在实验开始前,我们先梳理一下有什么工具或命令查看MySQL的阻塞,另外,我们也要一一对比其优劣,因为有些命令可能在实际环境下可能并不适用. ...

  2. oracle之子查询、创建用户、创建表、约束

      子查询                                    子查询可以分为单行子查询和多行子查询   单行子查询           [1] 将一个查询的结果作为另外一个查询的条 ...

  3. ArrayList源码和多线程安全问题分析

    1.ArrayList源码和多线程安全问题分析 在分析ArrayList线程安全问题之前,我们线对此类的源码进行分析,找出可能出现线程安全问题的地方,然后代码进行验证和分析. 1.1 数据结构 Arr ...

  4. 《Python黑帽子》_1设置Python环境安装wingIDE

    1首先你得有个Kali 检测python版本 安装pip 2安装wingIDE 网站 http://www.wingware.com 获取WingIDE 3解压wingide并且解决依赖关系 下载后在 ...

  5. Kinect SDK2.0 + OpenCV 3.0 抠人,换背景

    使用Kinect2.0的MultiSourceFrameReader,同时获取DepthFrameSource, ColorFrameSource, BodyIndexFrameSource,然后获取 ...

  6. 解决使用web开发手机网页关于分辨率被缩放的坑

    问题的产生 因为各方面原因,要用网页做界面,开发一个APP.内核使用的是腾讯的x5内核. 把外壳交给前端和设计测试的时候,都汇报:状态栏的颜色太不搭配了,要求可修改 遂启用了安卓4.4版本开始支持的沉 ...

  7. 【python标准库模块二】random模块学习

    random模块是用来生成随机数的模块 导入random模块 import random 生成一个0~1的随机数,浮点数 #随机生成一个0~1的随机数 print(random.random()) 生 ...

  8. Python 性能剖分工具

    Python 性能剖分工具 眼看着项目即将完成,却被测试人员告知没有通过性能测试,这种情况在开发中屡见不鲜.接下来的工作就是加班加点地找出性能瓶颈,然后进行优化,再进行性能测试,如此这般周而复始直到通 ...

  9. EBS业务学习之应付管理

    应付款系统是供应链管理的最后一个环节,它使公司能够支付供应商提供的货物和服务的费用.供应链管理的目标是保持低库存量但又有充足的存货以满足要求,仓库中的库存就等于钱,因此,应付款管理的目标是尽可能地推迟 ...

  10. [openresty]安装nginx_lua

    这种方式是直接安装openresty ,不是通过重新编译nginx Ubuntu 安装 安装依赖包 $ sudo apt-get install libreadline-dev libncurses5 ...