Java 第二条/第k条最短路径

Java 第二条/第k条最短路径,java,algorithm,dijkstra,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

使用下面的代码,我试图找到第二条最短路径/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;
        }
//在给定的图上运行Dijkstra算法
公共静态void最短路径(GraphModel图、int源、int目标、int numberoftexts)
{
//创建最小堆并推送距离为0的源节点
PriorityQueue minHeap=新的PriorityQueue((lhs,rhs)->lhs.weight-rhs.weight);
添加(新节点模型(源,0));
//初始设置从源到v的无限距离
List dist=new ArrayList(Collections.nCopies(numberoftexts,Integer.MAX_值));
//从震源到自身的距离为零
距离集(源,0);
//跟踪顶点的布尔数组,其最小值为
//成本已经找到
布尔[]完成=新布尔[numberOfVertices];
完成[0]=真;
//存储顶点的前身(打印路径)
int prev[]=新int[numberOfVertices];
prev[0]=-1;
//运行直到minHeap不为空
而(!minHeap.isEmpty())
{
//移除并返回最佳顶点
NodeModel节点=minHeap.poll();
node=minHeap.poll();
//获取顶点数
int u=node.vertex;
//为你的每个邻居v做些什么
对于(EdgeModel edge:graph.adjList.get(u))
{
int v=edge.dest;
int-weight=edge.weight;
//松弛步
如果(!done[v]&&(dist.get(u)+weight)
这是图表

    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)
    );
List edges=Arrays.asList(
新的EdgeModel(0,1,10),
新的EdgeModel(0,4,3),
新EdgeModel(1,2,5),
新EdgeModel(1,4,1),
新EdgeModel(2,3,7),
新EdgeModel(2,4,8),
新EdgeModel(3,4,2),
新EdgeModel(4,1,20)
);
从0到4的最短路径是3

从0到4的第二条最短路径是11


您可以使用
深度优先遍历算法检查从一个节点到B节点的所有路径。然后得到两条最短路径,一条或第二条最短路径。告诉我这是否有用。

您可以看一看日元算法。此算法用于查找第k条最短路径(多条路径)对于单一来源和单一目的地。该算法假设您已使用Djikstra或任何其他算法找到最短路径。以下是供您参考的链接:

您可以更新Dijkstra来完成此操作,您只需记住两个值-最短值和第二最短值。基本上,在浏览图形时,您会比较并保存两个值值。最短值相同,第二个值如下:

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

你将不得不接受你的第二个值——一旦它以与最短路径相同的方式存在于你的任何地方,第K条最短路径就是偏离所有K-1条较短路径的最短路径(可能有联系——任意打破它们)

要查找第k条最短路径,请执行以下操作:


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

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

然后,对于2..K,任务是添加不在trie中的最短路径。此路径将在某个点偏离trie中的。这意味着它将具有一条边,该边不跟随trie中的路径,但从trie中的路径开始。因此:

  • 遍历trie中的所有节点,并检查该节点上未被任何路径获取的边——每个边都表示一个偏差
  • 对于每个偏差,计算使用它的最短路径的长度。这在固定时间内很容易,因为你已经有了距离
  • 记住与最短新路径对应的偏差,并将包含该偏差的最短路径添加到trie中
添加到trie的最后一条路径是第k条最短路径


如前所述,这需要O((K+logv)(V+E))时间,这并不太糟糕。如果您在优先级队列中维护偏差,而不是每次都搜索它们,那么您可以在O(KV+E loge)中找到它,如果K很大,速度会更快。

我想这会发生在松弛过程中。你介意提供一些伪代码吗?对于第K个最短值,这将如何工作?是的,你需要在那里添加if语句,用于第二个值,在一般字段和逻辑中用于第二个值。我不在计算机atm机上,但我可以在8小时内提供一些代码这有点含糊不清,但我很确定这个答案并没有描述一个有效的解决方案。你可以使用
深度优先遍历
匹配所有路径。然后计算每条路径的距离。你可以使用自己的算法,dijkstra、Bellman Ford或其他什么。尽管获得所有路径都可行,但它也非常昂贵。O(2^n)不是我需要的解决方案,所以我相信现在的算法是寻找最短路径。我不认为它是通过反转边来实现的。“首先,从具有反转边的图上的目标开始运行Dijkstra算法,以在线性时间内找到每个顶点到目标的距离”-为什么Dijkstra的算法在线性t中运行