最短路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王国的王者.他的王国里有一个首都和一些城市.令人惊讶的是,现在王国没有道路.最近,他计划在首都和城市之间修建道路, ...
随机推荐
- 线段树练习5(codevs 4927)
题目描述 Description 有n个数和5种操作 add a b c:把区间[a,b]内的所有数都增加c set a b c:把区间[a,b]内的所有数都设为c sum a b:查询区间[a,b] ...
- 16.1114 模拟考试T1
1.正确答案 [题目描述] 小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案. “吔,我的答案和你都不一样!”,小Y说道,”我们去找神犇们问答案吧”. 外卡组试卷中共有m道判断题, ...
- 转 STL之vector的使用
http://www.cnblogs.com/caoshenghe/archive/2010/01/31/1660399.html 第一部分 使用入门 vector可用于代替C中的数组,或者MFC中的 ...
- Python入门--13--递归
什么是递归: 有调用函数自身的行为 有一个正确的返回条件 设置递归的深度: import sys sys.setrecursionlimit(10000) #可以递归一万次 用普通的方法也就是非递归版 ...
- Python入门--8--字符串
一.创建.修改字符串 str1='呆呆 槑槑 木木 林林' str1[1] #输出呆 str1[2] #输出' ',也就是空值 str1=str[:5]+'插入乖呆 '+str1[5:] #修改字符串 ...
- PAT (Advanced Level) 1088. Rational Arithmetic (20)
简单题. 注意:读入的分数可能不是最简的.输出时也需要转换成最简. #include<cstdio> #include<cstring> #include<cmath&g ...
- 【微信小程序】开发实战 之 「配置项」与「逻辑层」
微信小程序作为微信生态重要的一环,在实际生活.工作.商业中的应用越来越广泛.想学习微信小程序开发的朋友也越来越多,本文将在小程序框架的基础上就微信小程序项目开发所必需的基础知识及语法特点进行了详细总结 ...
- 多个Nginx如何实现集群(没具体方案,只是初步探究)
场景: Nginx+Web服务器可以实现负载均衡,但是一台Nginx也是有限的,如果并非量高的话,在他的上层如何实现负载均衡. 如果是DNS或者CDN的话,建多个机房,势必有多个机房数据同步的问题. ...
- go语言学习之路四:字典
关联数组:(哈希或者字典) Map是go内置关联数据类型,字典是通过Key来访问Value的,访问格式如下: Value=mapName[key] 其实数组可以看做是一个键值类型为整型的字典,可以说数 ...
- C/C++中static关键字作用总结 && 指针与引用的比较
static作用: 常规答案: 1. 全局变量的隐藏:2. 函数体内记忆功能:3.类所有实例共享,static函数不接受this指针,只能访问static成员变量. 拓展:1.全局变量的隐藏,因为在其 ...