最近在做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. GC机制

    java虚拟机中的垃圾回收机制是,一个类,当该对象没有更多的应用指向它时,就会被垃圾回收器给回收,从而释放资源.该机制不可以程序员手动调用去回收某个对象,系统自动会去调用,当然程序员可以建议垃圾回收器 ...

  2. ajaxStart()和ajaxStop()

    Jquery中当一个Ajax请求启动时,并且没有其他未完成的Ajax请求时,将调用ajaxStart()方法.同样,ajaxStop()方法则是在所有Ajax请求都完成时调用.这些方法的参数都是一个函 ...

  3. 在Linux系统上获取命令帮助信息和划分man文档

    使用历史命令history 打完以后前面会有顺序号的比如1 cd2 ls3 pwd如果需要重新执行cd命令则可以执行 !3 命令 命令补全功能 比如你要执行history命令 可以打上histo+键 ...

  4. spring cloud 入门系列三:使用Eureka 搭建高可用服务注册中心

    在上一篇中分享了如何使用Eureka 进行服务治理,里面搭建的服务注册中心是单体的, 但是在实际的应用中,分布式系统为了防止单体服务宕机带来严重后果,一般都会采用服务器集群的形式,服务注册中心也是一样 ...

  5. CRM客户关系管理系统(五)

    第五章.分页功能开发 5.1.修改BaseKingAdmin和完善前段页面显示 现在访问没有注册的model会报错,因为基类中没有写list_display和list_filter. 在基类中设置一个 ...

  6. ubuntu初始化python3+postgresql+uwsgi+nginx+django

    一. postgresql 数据库 安装 apt-get update apt-get install postgresql 进入psql客户端 sudo -u postgres psql 创建数据库 ...

  7. 安卓高级3 Android应用Design Support Library完全使用实例

    原作者:http://www.open-open.com/lib/view/open1433385856119.html 1 背景 上周一年一度的Google IO全球开发者大会刚刚结束,Google ...

  8. Bootstrap3 栅格系统-实例:响应列重置(Responsive column resets)

    四层的网格你肯定会遇到问题,可用在特定的断点,你的列不清楚作为一个比另一个高完全正确.为了解决这个问题,结合使用.clearfix和响应的实用工具类. <div class="row& ...

  9. linux2.6.37内核接两个硬盘导致读写效率变低的问题

    一.问题分析: 通过跟踪定位write系统调用的实现发现,在每次调用a_ops->write_end之后,都会去调用balance_dirty_pages_ratelimited,该函数负责检查 ...

  10. Ubuntu等Linux系统显卡性能测试软件 Unigine 3D

    Ubuntu等Linux系统显卡性能测试软件 Unigine 3D Ubuntu Intel显卡驱动安装,请参考: http://blog.csdn.net/zhangrelay/article/de ...