【问题标题】:All paths between two nodes in Boost Graph LibraryBoost Graph Library中两个节点之间的所有路径
【发布时间】:2015-05-08 10:23:21
【问题描述】:

我需要在图中找到两个节点之间的所有简单(非循环)路径。我了解如何通过修改后的广度优先搜索来实现这一点,因此正在查看 Boost 中的 BFS,但我看不到如何更改算法的步骤,只有访问者。

在我从头开始编写新算法之前,有没有办法在 BGL 中通过使用现有算法来实现这一点,无论是否有自定义访问者?

【问题讨论】:

  • 我...认为你是对的,你需要写这个。这不是一个搜索算法,真的。它更像是一个发电机。
  • 您可以考虑使用 DFS。我认为使用 DFS,您可以保留从起始节点开始的当前路径的堆栈,并在进行时推送和弹出边缘。在 inspect_edge 或 back_edge 上检查它是否指向您的目标节点。
  • hay,如果你有兴趣,boost中有boost::dijkstra_shortest_paths。您可能需要相应地准备数据结构。
  • 在这种情况下有用吗?我试图找到所有简单的路径,但 djikstra 只会给出给定顶点对的最短路径。

标签: c++ boost graph-theory boost-graph


【解决方案1】:

我们可能需要更多地了解您的图表。我有一个“类似”的问题。

这可能不是您正在寻找的,但它是相似的。这是我在有向图上使用的一个 DFS 访问者,它有一个根来计算从起始节点到所有其他(可达)节点的路径数。

这很有效,因为我的图是一个有根的 DAG。我必须先反转图表,以便我的起始节点实际上是一个接收节点。然后源节点成为 DAG 的根。如果我想要实际路径,我可能会添加一个告诉路径历史的堆栈。

//depth first search to calculate path number, calculates the number of paths to a target
// conceptually equivalent to a topological sort.
class PathNumDFSVisitor:public boost::default_dfs_visitor{

public:
    PathNumDFSVisitor(boost::unordered_map<std::string,std::size_t>& inMap):pathNumMap(inMap){}

    template < typename Vertex, typename Graph >
    void finish_vertex(Vertex u, const Graph & g)
    {
        std::string term = g[u].termId;

        if(boost::out_degree(u,g) == 0){
            pathNumMap[term] = 1;
        }else{
            pathNumMap[term] = 0;
            //Iterate over the children of the term to add the child annotations
            typename boost::graph_traits< Graph >::out_edge_iterator ei, e_end;
            for(tie(ei, e_end) = boost::out_edges(u, g); ei != e_end; ++ei){

                Vertex v = boost::target(*ei, g);

                std::string childTermId = g[v].termId;
                pathNumMap[term] += pathNumMap[childTermId];
            }
        }
    }

    boost::unordered_map<std::string,std::size_t>& pathNumMap;
};

不过,在一般情况下,我建议计算一条最短路径,然后依次获取每条边并找到从源到目标的替代路线。现在该边缘可能是两个或多个边缘,这反过来又需要放松并考虑替代路径。就像 Sehe 说的,它会是一个生成器,并且它可以在一般的无向图中快速爆炸。也许如果我们对您的图形约束有更多了解,我们可以提供更多帮助。

也许添加最大路径长度条件可以帮助限制您生成的简单路径的数量。

考虑这个一般的全连接图。

我们需要计算AB之间的所有路径。

所以我们需要所有 1 条边路径 + 所有 2 条边路径加上 ...

所以我们需要A - B,一个优势。

然后是所有 2 个边缘路径。 A - ? - B,有3个

然后所有 3 条边路径 A - ? - ? - B,有 3 * 2。

以此类推,有 4 个或更多边。

您可以看到随着 N 的增长,我们会达到 N-2 * N-3 * N-4 ... 等等。这是一个阶乘爆炸,O(N!)。

这些示例说明了不同的拓扑如何导致非常不同的算法和复杂性。要从 SO 中获得直接/有用的答案,请提供任何有帮助的细节。

【讨论】:

  • 我仍在尝试消化您的答案,但我的图表是无向且循环的。在这个阶段它是未加权的(后面进来的权重与这个阶段无关)。
  • 好的,这只是一个扩展的 DFS/拓扑排序。它将计算从源到所有其他节点的路径数。我认为在一般情况下,生成所有无向简单路径是 O(N!)。也许限制总路径长度可以让您避免如此详尽的搜索。
  • 不妨看看here。我意识到这不是一个真正的答案。我会留下它以防它可以帮助某人。
  • 在非全连接图的情况下(可能是我的情况),假设您有两条路径不共享任何边或在源和目标以外的任何点相遇,如果您从一条路径作为原始路径开始并使用此方法进行搜索,您会找到另一条路径吗?
  • @Joe 使用我描述的从最短路径开始的启发式方法可能是正确的。我在第二部分中描述的路径生成将找到所有简单路径,即使对于非完全连接的图也是如此。我只是想告诉你,根据你的图表的大小,这将是非常昂贵的。将搜索限制在一定长度以下的路径会有很大帮助。
猜你喜欢
  • 2019-04-23
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 2017-08-21
  • 1970-01-01
  • 1970-01-01
  • 2014-07-09
  • 2012-12-15
相关资源
最近更新 更多