一、问题介绍
1.求K条最短路径的必要性
最短路径问题分为:
单源最短路径
所有顶点对间的最短路径
共同的缺陷:
这里的最短路径指两点间最短的那一条路径,不包括次短、再次短等路径。这样的最短路径问题比较狭义。
在实际情况中,例如:用户在使用咨询系统或决策支持系统时,希望得到最优的决策参考外,还希望得到次优、再次优等决策参考,这同样反映在最短路径问题上。因此有必要将最短路径问题予以扩展和延伸,称为K条最短路径问题,即不但要求得最短路径,还要求得次短、再次短等路径。
2.KSP问题定义
KSP问题是对最短路径问题的推广,它除了要确定最短路径之外,还要确定次短路径、第三短路径,...,知道找到第K短路径。用Pi表示从起点s到终点t的第i短路径,KSP问题是确定路径集合Pk={p1,p2,p3,...,pk},使得满足以下3个条件:
1)K条路径是按次序产生的,即对于所有的i(i=1,2,...,K-1),pi是在pi+1之前确定;
2)K条路径是按长度从小到大排列的,即对于所有的i(i=1,2,...,K-1),都有c(pi)
3)这K条路径是最短的,即对于所有的p∈Pst-PK,都有c(pk)
3.相关概念
用于说明偏离概念的图
设起点为 1 ,终点为 5 。p1、p2、p3 分别表示起点到终点间最短路径、第二短路径、第三短路径。
1)偏离点
p3相对于p1的偏离节点为节点 2
2)偏离边
p3相对于p1的偏离边为(2,4)
3)偏离路径
p3相对于p1的(2,4,5)
4.KSP算法分类
1) 一般KSP问题
对路径没有任何限制
2) 限定无环KSP问题
要求所有路径都是简单路径,不能有环
当路径中所有节点都不同时,称为无环路径
两类KSP问题具有不同的特征,分别提出了不同的求解算法,分别称之为
一般的KSP算法
限定无环KSP算法
K最短路径算法分类
二、思路
下面列出用Yen's算法求KSP的代码。该算法是Yen在1971年提出的以其名字命名的Yen算法。算法采用了递推法中的偏离路径算法思想,适用于非负权边的有向无环图。
1.流程图
Q:将什么样的点做为偏离点
在pk的基础上求pk+1时,将pk的路径上除终点d之外的节点分别作为偏离点
Q:求Vi到终点d的最短路径
设起点为s,终点为t,偏离点为Vi。求偏离点到终点的最短路径时要注意两个问题
防止从起点到终点的整体路径有环
从Vi到t的最短路径不能包含s到Vi的路径上的任何节点
避免与已经在结果列表中的路径重复
从Vi发出的边不能与结果列表中的路径p1,p2,...pk,上从Vi发出边的相同
这个体现在代码上就是:在用Dijkstra算法算最短路径时对数组的初始化要进行特别处理
// 不能走的边
if (unavailableEdges != null && unavailableEdges.size() != 0) {
for (MyPath p: unavailableEdges) {
int index = p.path.indexOf(startIndex);
if (index >= 0 && (index + 1) >= 0) {
dist[index + 1] = Double.MAX_VALUE;
path[index + 1] = -1;
}
}
}
// 不能走的点
if (unavailableNodeIndexs != null && unavailableNodeIndexs.size() != 0) {
for (Integer point: unavailableNodeIndexs) {
set[point] = 1;
}
}
Q:每次找到新的最短路径时,需将该路径从候选链列表中移除,并加入到结果列表中
Q:候选列表中的路径不能重复
所以选择用Set来存储候选路径,去重
Q:如何从候选列表中选出合适的路径
如果只有一条路径权值和最小的路:将该路径返回;
如果路径权值和最小的路有多条:从其中选出节点数最少的路径。
2.手工模拟求K最短路径流程
求C到H的10条最短路径
节点加载内存后存储在Node[] nodes数组中,各个节点在数组中的存储位置如下,下面用各个点的数组下标进行说明。表格中括号中备注为路径权重。
1)通过最短路径算法Dijkstra得到C到H的最短路径
p