最短路Dijkstra算法的一些扩展问题
最短路Dijkstra算法的一些扩展问题
很早以前写过关于A*求k短路的文章,那时候还不明白为什么还可以把所有点重复的放入堆中,只知道那样求出来的就是对的。知其然不知其所以然是件容易引发伤痛的事啊,前天一次pku的比赛就得到了应验,因此下决心把这一类的问题要好好想一想。
搞了一天,总算有点成果,在此就总结一下这几类问题:
- 两点间的最短路的条数;
- 多关键字的极短路问题;
- 给定长度的路的条数;
- K短路及其条数;
- 标号法的一些看法;
- 程序设计与实现。
在此,先说明几个符号:
label 是每次出堆的一个标号;
struct label
int vertex; // 该标号所代表的顶点
int val; // 标号的值
};
phi(x):顶点x的标号,即源到该点的最短路
f(x):源到x的路径条数
S和T:分别是源和汇
if phi(s)+v==phi(t) then f(t)+=f(s)
else if phi(t)>phi(s)+v then f(t)=f(s)
不用再多说了吧,这不是今天的重点,略过。
多关键字的问题也是很具有实际意义的,就以双关键字为例子,其它的可以扩展。比如交通网络中的路一般都有收费和用时两个参量,在这种情况 下,就不存在一个最的定义,相应的,若用(cost,time)来表示一个标号,那么显然标号不再是一个全序而是偏序。在堆中比较两个标号可以采用第一、 第二关键字分别比较的方法,因此每次出堆的一定是一个极小的标号。由于每个顶点可以存在多个标号,因此对每个点维护一个标号的集合。如果把这个集合排序的 话,那么一定是按cost严格递增,同时按time严格递减。
1.label.val-phi(x)<=delta;
2.label.val+lambda(x)<=L 时才有希望。
可以发现,式子中的lambda就是用作A*的启发函数,因此我们把问题3就归结到了问题4,下面将一起处理。
问题4,这是本文的核心,我将详细说明。
我们知道A*对空间的要求是很高的,如果用扩展dijkstra的话则解收敛的更慢,因此更无法接受。如何优化扩展的顶点的数量就成了要亟待解决的关键问题。
定义: 将上面的delta我们称为冗余度,把每个点x分裂成独立的x+delta个顶点,那么这样形成的新图成为层次图。
用G’代表该层次图,那么G’的形态是怎样的呢?假想把原图G复制delta份按0,1,2顺序依次画出来,那么x+k所在的图就是第k层图。相应 扩展其他概念,用phi(x,k)表示从(S,0)到(x,k)的最短距离,f(x,k)表示到达(s,k)的最短路数量。对某条边(s->t, v)来说,若phi(s,k)+v==phi(t,k),即该边连接的点在同层,否则一定有phi(s,k)+v==phi(t,k’),k’> k,因此顺着这条边走就到达了下一层。
有了这个概念,不难知道我们要求的就是f(T,delta),即从(S,0)->(T,delta)的最短路的数量,化为我们已解决的问题1。但这还没完,层次图毕竟是个概念,在实现中要怎么解决呢?继续看下文。
要注意的是 (S,k),k>0是不存在的,这很容易理解。
对于一个求最大值的问题,如果能用标号法解决,当且仅当未知问题->未知问题的解决时间非负,即满足单调性。若要求解的数量,解决时间必须为正,即严格单调性。
这个性质很有意思,它只要求未知问题间的解决时间非负,因此联想到dijkstra算法,由于开始的时候S是已知问题,所以从S连出去的边是可以为负的,这在很多的书中都没有提到,因此很多人对dijkstra的理解也就停留在了机械记忆的阶段。
好了,
Run dijkstra in the 0’th level,那么phi(x,0)就是已知的了。
while ( heap is not empty )
Get a minimal label From min-heap
For any edge along go outside this label , (s->t,v):
length=label.val+v;
k=label.val-phi(s,0);
theta=length-phi(t,0);
if ( theta <= delta )
f(t,theta)+=f(s,k);
if (t,theta) is not in heap
}
}
从代码中我们也看出,其实编程中并没用到phi(x,k),k>0,所以其实保留phi(x)就可以了。
最后计算下复杂度。|V’|<=delta*|V|,|E’|<=delta*(|E|+|V|^2),所以总复杂度O(delta*V^2*(lgV+lg(delta)),这实际上也是在以前的文章中遗留的用A*求K短路的复杂度上限。
好了,问题都解决了。可是仍然不够圆满,因为新问题又来了,如果delta比较大该怎么做呢?还是有办法,可以利用K短路算法解决。
最短路Dijkstra算法的一些扩展问题的更多相关文章
- 单源最短路dijkstra算法&&优化史
一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结 最朴素算法: 邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+ML ...
- 单源最短路Dijkstra算法——matlab实现
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...
- 单源最短路——dijkstra算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 问 ...
- ACM: HDU 2544 最短路-Dijkstra算法
HDU 2544最短路 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Descrip ...
- hdu2544 最短路 Dijkstra算法
最短路(Dijkstra算法模板题) Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- 单源最短路(Dijkstra算法)
#返回上一级 @Author: 张海拔 @Update: 2015-03-11 @Link: http://www.cnblogs.com/zhanghaiba/p/3514570.html Dijk ...
- POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。
POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbe ...
- POJ-3268-最短路(dijkstra算法)
Silver Cow Party Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 12494 Accepted: 5568 ...
- 【Aizu - 2249】Road Construction(最短路 Dijkstra算法)
Road Construction Descriptions Mercer国王是ACM王国的王者.他的王国里有一个首都和一些城市.令人惊讶的是,现在王国没有道路.最近,他计划在首都和城市之间修建道路, ...
随机推荐
- 【bzoj4408】[Fjoi 2016]神秘数 主席树
题目描述 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1+13 = 1+1+14 = 45 = 4+16 = 4+1+1 ...
- 【Luogu】P3052摩天大楼里的奶牛(状压DP)
参见ZHT467的题解. f[i]表示在i这个集合下的最少分组数和当前组最少的容量. 从1到(1<<n)-1枚举i,对于每个i枚举它的子奶牛,然后重载运算符计算. 代码如下 #includ ...
- POJ——3984迷宫问题(BFS+回溯)
迷宫问题 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14568 Accepted: 8711 Description ...
- 10款GitHub上最火爆的国产开源项目
衡量一个开源产品好不好,看看产品在 GitHub 的 Star 数量就知道了.由此可见,GitHub 已经沦落为开源产品的“大众点评”了.一个开源产品希望快速的被开发者知道.快速的获取反馈,放到 Gi ...
- VScode开发Vue初尝试(一)
由于公司近期有新的H5项目开发,而前端的同事也离职了,所以就临时顶缸,研究学习一下Vue框架开发. 本人也是初学,在学习过程中,把一些学习所得分享出来,可能会有很多问题和疏漏,希望大家能够多多指正,共 ...
- css可见性
overflow:hidden: 溢出隐藏 visibility:hidden: 隐藏元素,隐藏之后还占据原来的位置 display:none: 隐藏元 ...
- [WASM] Create a New Rust/Webpack Project using the rust-webpack Template
Previous to this post, we set up our own Rust/wasm project from scratch. The Rust/wasm team ships a ...
- 自动检查出修改的代码 shell 做升级包 供观摩
#!/bin/bash # 检测出 appsReleass 项目代码更新 # oath 冉幕飞 #验证 基础参数 $1 day=$1 #多少天内 zipfile=$2 #包名称 if [ " ...
- 安卓自己定义View进阶-Canvas之绘制基本形状
Canvas之绘制基本形状 作者微博: @GcsSloop [本系列相关文章] 在上一篇自己定义View分类与流程中我们了解自己定义View相关的基本知识,只是,这些东西依然还是理论,并不能拿来(zh ...
- linux系统之shell编程-正則表達式
shell编程正則表達式: 1:元字符 [ ] . * ? + ( ) | { } ^ $ 2 : [a-z0-9] 表示匹配随意数字和字母的一个 3 : [^a-z] ...