我可以使用哪种算法查找图中最短路径的旁边?

时间:2011-02-11 17:02:50

标签: algorithm graph

我想找到图中2个顶点之间的下一个最短路径,并且路径具有正成本。允许下一个最短路径共享最短路径的边缘。我可以使用哪种算法?

8 个答案:

答案 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。

http://www.ics.uci.edu/~eppstein/pubs/Epp-TR-94-26.pdf

答案 1 :(得分:11)

我怀疑这在运行时间方面是最佳的,但是:

  1. 在图G上使用Dijkstra算法得到路径P
  2. 对于路径P中的所有边E:
  3. - 如果未连接G-E,请继续下一个边缘(转到2)
  4. - 在G-E上使用Dijkstra算法查找路径X_i
  5. - 如果当前X_i的长度短于所有其他X_i,请保存
  6. for循环结束时的X_i是第二条最短路径
  7. 第二条最短的路径无法通过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)

这个答案假设您正在寻找边缘不相交的第二条最短路径,这意味着第二条最短路径不能与最短路径共享任何公共边缘。

回想一下,两个节点AB之间的网络中的maximum flow为您提供了这两个节点之间的边缘不相交路径的数量。还要记住,Edmonds-Karp等算法的工作方式是在每个步骤通过最短路径发送流量。

因此,如果两个节点之间的最大流量大于1,则此问题只有解决方案。 1,每个边的容量为1.如果是,找到两个增强路径,如Edmonds-Karp算法中所述,第二个是你的第二个最短路径。

请参阅this problemthis 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;
}

EdgeWeightedDigraphMinPQ来自k shortest path routing

https://github.com/kevin-wayne/algs4

k = 1,p = [0,1,2,3]

k = 2,p = [0,4,5,3]