单源最短路:Dijkstra算法 及 关于负权的讨论
描述:
对于图(有向无向都适用),求某一点到其他任一点的最短路径(不能有负权边)。
操作:
1. 初始化:
一个节点大小的数组dist[n]
源点的距离初始化为0,与源点直接相连的初始化为其权重,其他为无穷大(INT32_MAX等)。
标记源点,其到自身距离是0,已经是最小了。
2. 计算
对于dist,每次选取未标记的最小值(将其标记,表示已经得到最小值),更新与其相连的未标记的点:
如果此点加上权值,小于与其相连的点,则更新之。
代码:
代码并未优化,理解思路即可。
#include <string>
#include <iostream>
#include <vector>
using namespace std; void Dijkstra() {
int source = ; // starting point
int vex, edge;
cout << "Input the number of vertexs and edges:" << endl;
cin >> vex >> edge;
vector<vector<int> > g = vector<vector<int> >(vex, vector<int>(vex)); // 用二维矩阵储存 int start, end, weight;
while(cin >> start >> end >> weight)
g[start][end] = weight; vector<int> res(vex, INT32_MAX);
vector<bool> visit(vex, false); res[source] = ;
visit[source] = true;
// 初始化
for (int i = ; i < vex; ++i)
if (i != source && g[source][i] != )
res[i] = g[source][i];
// 两层for循环
for (int i = ; i < vex; ++i) {
int min_element = INT32_MAX;
int min_index = -;
// 找出最小点
for (int j = ; j < vex; ++j) {
if (!visit[j] && res[j] < min_element) {
min_index = j;
min_element = res[j];
}
}
if (min_element == INT32_MAX || min_index == -)
break;
// 更新与其直接相连的所有点
for (int j = ; j < vex; ++j)
if (g[min_index][j] != &&
g[min_index][j] + res[min_index] < res[j] &&
!visit[j]) {
res[j] = g[min_index][j] + res[min_index];
visit[min_index] = true;
}
} for (int i = ; i < vex; ++i)
cout << res[i] << endl;
}
证明:
一。第一次选择:

初始数组是0, 30, 50, 20, 其他是无穷大。
此时选择点3,标记,由于其他出路都大于20,不存在任一条路能更快到达3。
二。任一次选择:

设我们选择了与k相连的i点,将其标记。
需要证明不存在未标记的点j,使得存在一条路径更快到达i点。
不可能的存在,因为如果存在则不可能标记 i,源点到达 j 的距离比到 i 距离近,而 j 前面必定存在被标记的一点s(至少是源点),至少从s开始标记。
证毕。(严格的推导可以设具体变量证明)
关于负权的讨论:
要区分负权边和负权环的概念。
负权边:权重为负数的边。
负权环:源点能到达的一个环,环上权重和为负数。
Dijkstra算法不能包含负权边,含有负权环可以用bellman-ford算法计算。
即使不是负权环,Dijkstra也不能算,如果加入负边,上面证明就不成立。
负权环不存在最短路!
关于Dijkstra算法不能计算负权边:
不是说对于所有含有负权的图都不能计算,如下可以计算:
当负权边指向一个有唯一入边的情况:

碰巧:

还有其他情况。所以,如果含有负权边使用Dijkstra算法,可能对可能错。
有些不能计算:

这种情况,第一次会选择 点2,标记最短路径为3,实际最短是0->1->2,距离为2。
复杂度:
用邻接矩阵储存的图:
复杂度为O(V^2 + E),但E最大也不过V^2,也可以表示为O(V^2)。
原因:外层for循环,O(V)。内层,查找最小点O(V),更新这点的每条边e,
则:V(V + e) => V^2 + Ve,总共E条边,即V^2 + E。邻接表也一样。
用二叉堆维护最短距离数组:
复杂度为O((V + E)logV)。
原因:外层仍然是V。内层,取出最小值logV,更新点的e条边,且需要入堆,则为elogV,
则:V(logV + elogV) => VlogV + VelogV => VlogV + ElogV => (V + E)logV。
关键在于堆本来是空的,每次更新,都将其入堆,然后从堆中选出最小的,将其标记,可以参考其实现代码理解。
用斐波那契堆维护的最短距离数组:
复杂度:O(VlogV + E)
查下这种堆各操作复杂度即可知道,入堆为O(1),弹出为O(logN),则同上:
V(logV + e),即VlogV + E。
单源最短路:Dijkstra算法 及 关于负权的讨论的更多相关文章
- 单源最短路dijkstra算法&&优化史
一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结 最朴素算法: 邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+ML ...
- 单源最短路——dijkstra算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 问 ...
- 单源最短路Dijkstra算法——matlab实现
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...
- 单源最短路(Dijkstra算法)
#返回上一级 @Author: 张海拔 @Update: 2015-03-11 @Link: http://www.cnblogs.com/zhanghaiba/p/3514570.html Dijk ...
- 单源最短路-dijkstra算法(未优化)
bool used[maxn]; int g[maxn][maxn]; // 边未联系的填充为INF int d[maxn]; void dijkstra(int s){ memset(g,false ...
- 0016:单源最短路径(dijkstra算法)
题目链接:https://www.luogu.com.cn/problem/P4779 题目描述:给定一个 n 个点,m 条有向边的带非负权图,计算从 s 出发,到每个点的距离. 这道题就是一个单源最 ...
- 单源最短路径(dijkstra算法)php实现
做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...
- 【算法】单源最短路——Dijkstra
对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...
- 利用分支限界法求解单源最短路(Dijkstra)问题
分支限界法定义:采用Best fist search算法,并使用剪枝函数的算法称为分支界限法. 分支限界法解释:按Best first的原则,有选择的在其child中进行扩展,从而舍弃不含有最优解的分 ...
随机推荐
- 解决maven install报错信息(Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile )
Maven install失败 Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (d ...
- js 验证手机号码
js 验证手机号码 //验证手机号 function isMobel(value) { if (/^1[3-8]+\d{9}$/g.test(value)) { ...
- 使用 某款基于Socks5协议的代理软件 一段时间后 被封锁掉IP的一些技术思考
由于关键词比较敏感为了不被删除帖子所以文中某软件(上图所示软件)不用全称表示. 去年9月末在 在某国外网站 上弄了一个vpn,在上面安装了某软件,使用起来还是蛮不错的,平时查查英文论文,看看美剧还是比 ...
- 替换国内yum源以及pip源
因为一些原因,不论是网络还是啥啥啥的原因,国外的源访问时不时的很慢,这时候我们就可以将国外的源替换为国内源,提高下载速度. yum源替换 环境:centos7(如果你的发行版本不是这个,此方法不保证能 ...
- MacOS 如何截屏
在Mac OS X下有很强大的截屏功能,它不仅仅是对屏幕的全屏COPY,而是包括很多细节在里面,就从这点来看,已经比过所有版本的Windows了. 下面我来向大家详细介绍一下: 对全屏的截图我们可以通 ...
- rsync 通过密码文件实现远程同步
https://my.oschina.net/yyping/blog/91964 1.源文件服务器:192.168.10.203 2.备份服务器:192.168.10.88 配置备份服务器(192.1 ...
- postgresql PL/pgSQL—存储过程结构和变量声明
ref: https://www.postgresql.org/docs/9.6/static/plpgsql-structure.html 一. 函数结构 CREATE FUNCTION somef ...
- 微信小程序详解——页面之间的跳转方式【路由】和参数传递
微信小程序拥有web网页和Application共同的特征,我们的页面都不是孤立存在的,而是通过和其他页面进行交互,来共同完成系统的功能.今天我们来研究小程序页面之间的跳转方式. 1.先导 在Andr ...
- create index 与 alter table add index 区别
众所周知,MySQL创建索引有两种语法,即:ALTER TABLE HeadOfState ADD INDEX (LastName, FirstName);CREATE INDEX index_nam ...
- php变量的实现
1.php变量的实现 变量名 zval ,变量值 zend_value,php7的变量内存管理的引用计数 在zend_value结构上,变量的操作也都是zend_value实现的. //zend_ty ...