Dijkstra算法可使用的前提:不存在负圈。

负圈:负圈又称负环,就是说一个全部由负权的边组成的环,这样的话不存在最短路,因为每在环中转一圈路径总长就会边小。

算法描述:

  1.找到最短距离已确定的顶点,从它出发更新相邻顶点的最短距离。

  2.以后不需要再关心1中的“最短距离已确定的顶点”。

C++代码:

#include <bits\stdc++.h>
using namespace std;
#define INF 2147483647
#define MAX_V 1000
#define MAX_E 2000 //单源最短路径问题(Dijkstra算法) int cost[MAX_V][MAX_V]; //cost[u][v]表示e = (u,v)的权值
int d[MAX_V]; //顶点s出发的最短距离
bool used[MAX_V]; //标记使用过的点
int V; //顶点数 void dijkstra(int s){
fill(d, d+V, INF);
fill(used, used + V, false);
d[s] = ; while(true){
int v = -; //找到一个距离最近的没有使用过的点
for(int u = ;u < V; u++){
if(!used[u] && (v == - || d[u] < d[v])) v = u;
}
//如果所有的点都被使用过了,则break
if(v == -) break; //标记当前点被使用过了
used[v] = true; //更新这个找到的距离最小的点所连的点的距离
for(int u = ;u < V; u++){
d[u] = min(d[u], d[v] + cost[v][u]);
} }
} int main(){
}

我们会发现,如果边比较少的话,用邻接矩阵特别耗时间和空间。

时间复杂度O(V^2)

所以边比较少的话,有一种邻接矩阵的写法,对其优化一下,

时间复杂度O(E*log(V))

C++代码:

#include <bits\stdc++.h>
using namespace std;
#define INF 2147483647
#define MAX_V 1000
#define MAX_E 2000 //单源最短路径问题(Dijkstra算法) struct edge{
int to,cost;
}; typedef pair<int, int> P; //first是最短距离,second是顶点的编号 int V; //顶点数
vector <edge> G[MAX_V]; // 边
int d[MAX_V]; // d[i]表示i离源点的最短距离 void dijkstra(int s){
//通过指定greater<P> 参数,优先队列是用堆实现的,堆按照first从小到大排序。
priority_queue<P, vector<P>, greater<P> > que; fill(d, d+V, INF);
d[s] = ; //加源点入最小堆
que.push(P(,s)); while(!que.empty()){
//取出堆顶的点,也就是距离最小的点
P p = que.top(); que.pop();
int v = p.second; //如果这个点在加入队列之后更新过,就不必再更新
if(d[v] < p.first) continue; //遍历当前点相邻的所有点
for(int i = ;i < G[v].size(); i++){
edge e = G[v][i];
//如果这个点能更新其他点,就将被更新的那个点加入队列。
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
} int main(){
}

路径还原:

#include <bits\stdc++.h>
using namespace std;
#define INF 2147483647
#define MAX_V 1000
#define MAX_E 2000 //单源最短路径问题(Dijkstra算法) int cost[MAX_V][MAX_V]; //cost[u][v]表示e = (u,v)的权值
int d[MAX_V]; //顶点s出发的最短距离
bool used[MAX_V]; //标记使用过的点
int V; //顶点数 int prev[MAX_V]; //最短路径上的前驱顶点 void dijkstra(int s){
fill(d, d+V, INF);
fill(used, used + V, INF);
fill(prev, prev+V, -); //初始化前驱数组
d[s] = ; while(true){
int v = -;
for(int u = ;u < V; u++){
if(!used[u] && (v == - || d[u] < d[v])) v = u;
}
if(v == -) break;
used[v] = true;
for(int u = ;u < V; u++){
d[u] = min(d[u], d[v] + cost[v][u]);
prev[u] = v; //记录每个点的前驱
}
}
} //获取起始点到顶点t的最短路径
vector <int> getpath(int t){
vector<int> path;
while(t != -){
path.push_back(t);
t = prev[t];
}
//获取的路径是逆序,需要翻转
reverse(path.begin(),path.end()); return path;
} int main(){
}

【算法】Dijkstra算法(单源最短路径问题)(路径还原) 邻接矩阵和邻接表实现的更多相关文章

  1. 【算法导论】单源最短路径之Dijkstra算法

    Dijkstra算法解决了有向图上带正权值的单源最短路径问题,其运行时间要比Bellman-Ford算法低,但适用范围比Bellman-Ford算法窄. 迪杰斯特拉提出的按路径长度递增次序来产生源点到 ...

  2. 【算法导论】单源最短路径之Bellman-Ford算法

    单源最短路径指的是从一个顶点到其它顶点的具有最小权值的路径.我们之前提到的广度优先搜索算法就是一种无权图上执行的最短路径算法,即在所有的边都具有单位权值的图的一种算法.单源最短路径算法可以解决图中任意 ...

  3. 经典贪心算法(哈夫曼算法,Dijstra单源最短路径算法,最小费用最大流)

    哈夫曼编码与哈夫曼算法 哈弗曼编码的目的是,如何用更短的bit来编码数据. 通过变长编码压缩编码长度.我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit.但在很多情况下,数 ...

  4. Dijkstra求解单源最短路径

    Dijkstra(迪杰斯特拉)单源最短路径算法 Dijkstra思想 Dijkstra是一种求单源最短路径的算法. Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀. Dijkstra算法主 ...

  5. 单源最短路径——dijkstra算法

    dijkstra算法与prim算法的区别   1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...

  6. 【转】Dijkstra算法(单源最短路径)

    原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...

  7. [数据结构与算法-15]单源最短路径(Dijkstra+SPFA)

    单源最短路径 问题描述 分别求出从起点到其他所有点的最短路径,这次主要介绍两种算法,Dijkstra和SPFA.若无负权优先Dijkstra算法,存在负权选择SPFA算法. Dijkstra算法 非负 ...

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

    一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...

  9. [C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

    1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 ...

  10. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

随机推荐

  1. Spark SQL概念学习系列之性能调优

    不多说,直接上干货! 性能调优 Caching Data In Memory Spark SQL可以通过调用sqlContext.cacheTable("tableName") 或 ...

  2. PHP 环境搭建工具

    PHP环境搭建工具 一键集成工具 直接安装后部署到相关目录即可浏览 phpStudy 下载地址:https://pan.baidu.com/s/1i6C3Ph7

  3. GCC中的弱符号与强符号

    GCC中的弱符号与强符号 我们经常在编程中碰到一种情况叫符号重复定义.多个目标文件中含有相同名字全局符号的定义,那么这些目标文件链接的时候将会出现符号重复定义的错误.比如我们在目标文件A和目标文件B都 ...

  4. Reflection (computer programming) -反射-自身结构信息

    n computer science, reflection is the ability of a computer program to examine, introspect, and modi ...

  5. C#基础篇之语言和框架介绍

    1.如何描述C#和.NET的关系? .Net的是平台,C#是为了微软公司为了.NET平台开发的面向对象语言. 2.C#能做什么? (1)C#.NET做窗体应用开发,Web开发中可以通过WCF编写Web ...

  6. Unity官方宣传片Adam 播放地址

    https://www.youtube.com/watch?v=GXI0l3yqBrA 适合吸引初学的人走下去,不知道你们初次看的时候什么感觉,反正我被震撼到了!(听说资源包有10个G!官方可下载) ...

  7. ZBrush中遮罩的概念及使用

    刚接触设计软件的小伙伴有可能不知道什么叫做遮罩,遮罩的概念是什么,顾名思义,遮罩就是可以将局部进行遮挡,使用它可以锁定和保护我们不想改变的模型位置,即被遮罩的部分将不参与任何编辑. ZBrush®软件 ...

  8. ZBrush中Flatten展平笔刷介绍

    本文我们来介绍ZBrush®中的Flatten展平笔刷,Flatten笔刷能增加粗糙的平面在模型表面,利用它能够制作出完全的平面. Flatten展平笔刷 Flatten(展平):Flatten笔刷可 ...

  9. 路飞学城Python-Day29(第四模块-并发编程)

    01-进程与程序的概念 并发:多进程和多线程 进程的概念:进程就是正在执行的过程,一个应用程序不是进程,只有应用程序启动以后才能说是进程,进程是一个抽象的概念,起源于操作系统 02-操作系统介绍 应用 ...

  10. Python笔记24-----迭代器、生成器的使用(如嵌套列表的展开、树的遍历等)

    1.递归yield使用: 嵌套列表展开 def flatten(nested): if type(nested)==list: for sublist in nested: for i in flat ...