在O(E logV)中查找图中的单调最短路径

此页面中存在创意问题的问题34。

单调最短路径。 给定一个边加权有向图,找出从s到其他每个顶点的单调最短路径。 如果路径上每个边的权重严格增加或严格递减,则路径是单调的。

部分解决方案 :按升序放松边缘并找到最佳路径; 然后按降序放松边缘并找到最佳路径。

我的问题:

假设我们按照降序来放松边缘,并且我们可以选择多于一个边缘来选择一个点。 我们选择下一个优势的依据是什么? 理想情况下,我们应该选择较小的边缘,因为它会最小化到该顶点的距离。 但是,如果所有离开它的边都具有大于当前边的权重的权重,那么这样做可能不会从该顶点产生更多路径。

那么,我们如何解决这个问题呢?


这个问题可以通过修改Dijkstra算法来解决。 主要的一点是,放松不应该在每个图节点(像往常一样)中进行min操作,而应该放在优先级队列中。

以下是通常Dijkstra算法的修改列表。 我只考虑边缘按升序放松,这会导致严格缩短最短路径(以获得最短路径,改变项目2和4):

  • 通过对来自每个节点的输出边进行排序(按重量)来预处理图。
  • 每个节点应包含出口边缘列表中的位置(由最轻边缘的位置初始化)。
  • 不需要优先队列来支持“减少”操作(所以它可以通过简单的最小堆来实现)。 每个顶点被插入到优先级队列中,然后从未改变,直到它出现在队列的顶部(因为每个顶点可以在队列中多次表示)。 队列条目由一个键(如通常的路径长度),顶点和输入边的权重组成。 所以我们可能会假定优先队列包含传入边而不是顶点。
  • 松弛过程:从队列中弹出边缘(因此该边缘结束的顶点); 对于顶点的所有输出边,按递增顺序从存储在图节点中的位置开始,并在输出边的权重大于或等于输入边的权重时结束,将输出边推到优先级队列并提前存储位置。
  • 该算法保证每条边最多处理一次(如果我们考虑严格递减和严格递增路径,则处理两次),因此其复杂度为O(E log E)。

    C ++ 11实现:

    void getDecreasingSP(Vertices& vertices, Edges& edges, int src)
    {
        for (auto& v: vertices)
            sort(begin(v.outEdges), end(v.outEdges),
                 [&](int from, int to)
                 {
                     return edges[from].weight < edges[to].weight;
                 });
    
        PQ pq;
        auto& src_v = vertices[src];
        for (auto e: src_v.outEdges)
        {
            QEntry entry {edges[e].weight, e};
            pq.push(entry);
            ++src_v.pos;
        }
    
        while(!pq.empty())
        {
            QEntry top = pq.top();
            pq.pop();
            auto& v = vertices[edges[top.inEdge].to];
    
            while (v.pos < int(v.outEdges.size()) &&
                edges[v.outEdges[v.pos]].weight < edges[top.inEdge].weight)
            {
                auto e = v.outEdges[v.pos];
                edges[e].backPtr = top.inEdge;
                QEntry entry {top.pathWeight + edges[e].weight, e};
                pq.push(entry);
                ++v.pos;
            }
    
            if (v.backPtr == -1)
                v.backPtr = top.inEdge;
        }
    }
    

    另见Ideone的工作代码。 并且通过Graphviz帮助显示图形(由此代码生成),其中严格递减的最短路径之一被突出显示:

    在这里输入图像描述

    链接地址: http://www.djcxy.com/p/35299.html

    上一篇: Find a monotonic shortest path in a graph in O(E logV)

    下一篇: FInding All Shortest Paths Between Two Vertices