【问题标题】:Graph algorithm to collect all edges which are on any path between two nodes图算法收集两个节点之间任意路径上的所有边
【发布时间】:2015-06-12 22:44:35
【问题描述】:

我需要在有向图中找到两个节点 [src, dest] 之间任意路径上的所有边。

表示每条边(从底部到头部)必须满足:

  • 有一条从 src 到 base 的路径
  • 从头到尾有一条路

我可以收集所有连接到 src 的边,收集所有反向连接到 dest 的边并计算它们的交集。

但总得有个算法吧? (不知道能不能有更高效的)所以我正在寻找名称,或者用现有算法解决它的聪明解决方案。

【问题讨论】:

  • 实施您的方法所需的所有步骤都在 O(|E|+|V|) 内。如果您想找到所有解决方案,那么您就没有比这更高效的了。
  • 假设“cut”只是指“intersection”(而“connected”是指“可到达”),那么正如@Zotta 所说,你不能做得更好。跨度>

标签: algorithm graph graph-algorithm


【解决方案1】:

如果您只回答一次问题,那么评论您问题的人是正确的:您提出的解决方案是正确且快速的。但是,如果您在固定图中针对不同的 src 和 dest 多次回答您的问题,则有一种方法可以“索引”信息以加快查询速度。

Tarjan's algorithm 将在 O(V+E) 时间内将有向图分解为强连通分量 (SCC)。强连通分量是一组通过有向图相互可达的顶点。

强连通分量的集合本身将形成一个有向无环图 (DAG)。

如果 src 和 dest 在同一个 SCC 中,那么您要查找的边集正是 SCC 中的边集。

如果包含 dest 的 SCC 从 DAG 中包含 src 的 SCC 无法到达,则没有从 src 到 dest 的路径,因此您要查找的边集是空的。

如果包含dest的SCC可以从包含src的SCC到达,则需要在DAG中找到从src SCC到dest SCC的所有路径,这是一个非常简单的动态规划问题。那么你想要的边集就是 src SCC 和 dest SCC 之间的所有 SCC 中的边集,加上 DAG 中相关路径的边到原始图中的边的“回调”。

这可能听起来令人困惑,但维基百科页面上的图表可能有助于澄清。

【讨论】:

  • 我不太明白你的意思。但是让我们看看例如一棵树,没有强连接的组件,但我的问题仍然有解决方案。我误解了你的回答吗?
  • 每个节点本身就是一个 SCC。这棵树就是 DAG。
  • 啊,好吧,所以一个scc可以reucable到一个节点,因为起点并不重要,所以我可以将问题简化为简化图。这实际上是一个有趣的优化,因为 scc 给了我有趣的信息...
【解决方案2】:

为了获得总体结果,我将报告我所做的事情。

我实现了问题中提到的算法。 (我们称之为 thigg 算法,因为没有人提到名字)

Thigg 算法:

for each node in the graph:
     if there is a path from src to this node 
        and a path from this node to dest, 
       push node to the result list.

正如 Edward Doolittle 在他的 answer 中提到的那样,可以通过识别强连接组件并将它们减少到一个节点来优化该图。这将减少算法在每次运行时的工作量。

我使用 Boost-Graph-Library(没有 SCC 优化)实现了 thiggs 算法,其中a 是源顶点,b 是目标顶点:

我使用广度优先搜索来获取a 可以访问的所有顶点的列表:

boost::breadth_first_search(graph, a, visitor(vis));

vis 是一个自定义访问者,它将所有访问过的顶点放到一个列表中。 然后它恢复图形以获取所有可以到达 b 的顶点

boost::breadth_first_search(boost::make_reverse_graph(graph), b, visitor(vis));

最后计算交集:

std::set_intersection(froma.begin(),froma.end(),fromb.begin(),fromb.end(),back_inserter(inters));

Note,您的图形必须是双向的才能使用make_reverse_graph

该算法也适用于问题中提到的边缘。

【讨论】:

    猜你喜欢
    • 2011-02-12
    • 1970-01-01
    • 2014-07-09
    • 2012-03-21
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    相关资源
    最近更新 更多