第二最短/第k个最短路径

时间:2019-07-17 16:23:33

标签: java algorithm dijkstra

使用下面的代码,我试图找到第二条最短路径/第k条最短路径。

// Run Dijkstra's algorithm on given graph
    public static void shortestPath(GraphModel graph, int source, int destination, int numberOfVertices)
    {
        // create min heap and push source node having distance 0
        PriorityQueue<NodeModel> minHeap = new PriorityQueue<>((lhs, rhs) -> lhs.weight - rhs.weight);
        minHeap.add(new NodeModel(source, 0));

        // set infinite distance from source to v initially
        List<Integer> dist = new ArrayList<>(Collections.nCopies(numberOfVertices, Integer.MAX_VALUE));

        // distance from source to itself is zero
        dist.set(source, 0);

        // boolean array to track vertices for which minimum
        // cost is already found
        boolean[] done = new boolean[numberOfVertices];
        done[0] = true;

        // stores predecessor of a vertex (to print path)
        int prev[] = new int[numberOfVertices];
        prev[0] = -1;

        // run till minHeap is not empty
        while (!minHeap.isEmpty())
        {
            // Remove and return best vertex
            NodeModel node = minHeap.poll();
            node = minHeap.poll();
            // get vertex number
            int u = node.vertex;

            // do for each neighbor v of u
            for (EdgeModel edge: graph.adjList.get(u))
            {
                int v = edge.dest;
                int weight = edge.weight;
                // Relaxation step
                if (!done[v] && (dist.get(u) + weight) < dist.get(v))
                {
                    dist.set(v, dist.get(u) + weight);
                    prev[v] = u;
                    minHeap.add(new NodeModel(v, dist.get(v)));
                }
            }

            // marked vertex u as done so it will not get picked up again
            done[u] = true;
        }

这是图。

    List<EdgeModel> edges = Arrays.asList(
            new EdgeModel(0, 1, 10), 
            new EdgeModel(0, 4, 3),
            new EdgeModel(1, 2, 5), 
            new EdgeModel(1, 4, 1),
            new EdgeModel(2, 3, 7), 
            new EdgeModel(2, 4, 8),
            new EdgeModel(3, 4, 2), 
            new EdgeModel(4, 1, 20)
    );
  

从0-4开始的最短路径是3

     

从0-4开始的第二条最短路径是11

enter image description here

4 个答案:

答案 0 :(得分:1)

您可以看一下日元算法。该算法用于查找单个来源和单个目的地的第k条最短路径(多条路径)。该算法假定您已使用Djikstra或任何其他算法找到了最短路径。这是供您参考的链接:https://en.wikipedia.org/wiki/Yen%27s_algorithm

答案 1 :(得分:0)

您可以使用Depth First Traversal算法检查从A节点到B节点的所有路径。然后得到两个最短的一条或第二条最短的路径。告诉我是否有帮助。

答案 2 :(得分:0)

您可以更新Dijkstra来做到这一点,您只需要记住两个值-最短和第二个最短。基本上,当您浏览图形时,您将比较并保存两个值。最短的是相同的,第二个是以下的:

  • 没有第二个,比较时保存新值
  • 更好的路径-将现有路径保存为第二个值
  • 这不是更好的路径,但是比现有的更好-替换第二个

您将不得不取第二个值-一旦它以最短的一个值存在于您随处可见

答案 3 :(得分:0)

第K条最短路径是偏离所有K-1条较短路径的最短路径(可能有联系-任意打破它们)。

找到第K条最短路径:

首先,从具有反向边的图形上的目标开始运行Dijkstra的算法,以对数线性时间找到从每个顶点到目标的距离。对于每个顶点,这使您可以立即确定从该顶点开始的最短路径的长度,并轻松找到它。

然后,将最短路径放入特里。这是第一条最短路径。

然后,对于2..K,任务是添加不在trie中的最短路径。在某些时候,这条路径会偏离。这意味着它将有一条边缘,不遵循特里中的路径,但起始于中。所以:

  • 遍历trie中的所有节点,并检查任何路径未在该节点处取得的边缘-每个边缘代表一个偏差。
  • 对于每个偏差,计算使用该偏差的最短路径的长度。由于您已经有了距离,因此在恒定时间内这很容易。
  • 记住对应于最短新路径的偏差,并将包含该偏差的最短路径添加到trie。

您添加到trie的最后一条路径是第K条最短的路径。

如前所述,这需要O((K + log V)(V + E))时间,这还不错。如果您将偏差保留在优先级队列中,而不是每次都进行查找,则可以在O(KV + E log E)中进行查找,如果K大,则速度更快。