我想找到图中2个顶点之间的下一个最短路径,并且路径具有正成本。允许下一个最短路径共享最短路径的边缘。我可以使用哪种算法?
答案 0 :(得分:15)
使用K最短路径算法,其中k = 2,一些示例参考:
找到k个最短路径。 D.埃普斯坦。 第35届IEEE Symp。 Comp的基础Sci。,Santa Fe,1994,pp.154-165。 技术。 Rep.94-26,ICS,UCI,1994。 SIAM J. Computing 28(2):652-673,1998。
答案 1 :(得分:11)
我怀疑这在运行时间方面是最佳的,但是:
第二条最短的路径无法通过P中的所有边缘,但它可能会经历除了其中一条之外的所有边缘。我认为“第二短”不会多次使用边缘,否则第二短路径可能包含P.
答案 2 :(得分:4)
一种方法是使用Floyd-Warshall算法找到所有对最短路径然后测试所有中间边缘是一种肯定 - 但可能不是最佳方式 - 来解决这个问题。这是一个很好的解释 http://hatemabdelghani.wordpress.com/2009/07/04/second-shortest-path/
答案 3 :(得分:3)
这假设您可以重复使用边和节点:
直接的解决方案是扩展Djikstra算法。
不是为每个节点存储最小的成本及其相应的父级,而是存储两个最小的成本(及其各自的父级)。
对于优先级队列,存储节点,存储(节点,i)对的内容,所以你知道在传播过程中使用第一或第二路径。
在传播阶段注意保持多路径值的正确更新。
(我可能会遗漏一些重要细节,但基本想法就在这里......)
答案 4 :(得分:2)
使用shortest path algorithm查找最短路径P.
然后您可以将此问题视为constraint satisfaction problem(其中约束是“非P的最短路径”),并使用backtracking algorithm查找不是最短路径的最短路径你已经找到的路径。
答案 5 :(得分:2)
这个答案假设您正在寻找边缘不相交的第二条最短路径,这意味着第二条最短路径不能与最短路径共享任何公共边缘。
回想一下,两个节点A
和B
之间的网络中的maximum flow为您提供了这两个节点之间的边缘不相交路径的数量。还要记住,Edmonds-Karp等算法的工作方式是在每个步骤通过最短路径发送流量。
因此,如果两个节点之间的最大流量大于1,则此问题只有解决方案。 1,每个边的容量为1.如果是,找到两个增强路径,如Edmonds-Karp算法中所述,第二个是你的第二个最短路径。
请参阅this problem和this solution(说明是中文的。我无法翻译,babelfish也不能真正做到,但不会承认。代码(例如,很容易理解)。
答案 6 :(得分:0)
如果您更喜欢学术性的实用解决方案,那么就是一个。
我通过设置对最短路径边缘的惩罚并再次运行搜索来解决这个问题。
E.g。最短路径长度为1000,罚分为10%,因此我搜索第二条最短路径1000< = length< = 1100。
在最坏的情况下,我找到了以前的最短路径 在最好的情况下,我找到一个长度相同的分离路径 在大多数情况下,我发现共享一些局部最佳子路径的路径。
增加惩罚迫使算法找到替代路线,而减少使得它共享容忍。
当我找到第二条最短路径时,我必须从计算长度中减去共享边上的惩罚总和,以得到实际长度。
对于第k个最短路径,我将惩罚设置为先前k-1个最短路径中使用的所有边。
答案 7 :(得分:0)
您正在寻找docs。基本上,运行修改过的Dijkstra,但不要将边缘保留在min-heap上,而是要保留到目前为止找到的所有路径。
我更喜欢工作代码,因为魔鬼总是很详细:
@SuppressWarnings("unchecked")
public static Iterable<Integer>[] kShortestPaths(EdgeWeightedDigraph g, int s, int t, int k) {
if (k <= 0) throw new IllegalArgumentException("k must be positive");
boolean[] visited = new boolean[g.V()];
int[] count = new int[g.V()];
MinPQ<Map.Entry<Map.Entry<Integer, Double>, Queue<Integer>>> heap = new MinPQ<>(
comparingDouble(e -> e.getKey().getValue())
);
Queue<Integer>[] p = (Queue<Integer>[]) new Queue<?>[k];
heap.insert(new SimpleImmutableEntry<>(new SimpleImmutableEntry<>(s, 0.0d), new Queue<>()));
int i = 0;
while (!heap.isEmpty()) {
Map.Entry<Map.Entry<Integer, Double>, Queue<Integer>> node = heap.delMin();
Integer u = node.getKey().getKey();
if (count[u] >= k) break;
Queue<Integer> pathU = node.getValue();
visited[u] = true;
pathU.enqueue(u);
if (u == t) {
p[i] = new Queue<>();
for (int w : pathU) {
p[i].enqueue(w);
}
i++;
}
if (count[u]++ <= k) {
double costU = node.getKey().getValue();
for (DirectedEdge e : g.adj(u)) {
int v = e.to();
if (!visited[v]) {
Queue<Integer> pathV = new Queue<>();
for (int w : pathU) {
pathV.enqueue(w);
}
heap.insert(new SimpleImmutableEntry<>(new SimpleImmutableEntry<>(v, e.weight() + costU), pathV));
}
}
}
}
return p;
}
EdgeWeightedDigraph
和MinPQ
来自k shortest path routing。
https://github.com/kevin-wayne/algs4
k = 1,p = [0,1,2,3]
k = 2,p = [0,4,5,3]