如何查找给定图形的每对顶点之间是否存在路径?

时间:2015-09-28 11:39:26

标签: c++ graph graph-theory depth-first-search

要查找有向图中每对顶点之间是否存在路径,我正在检查是否可以使用DFS从特定顶点访问所有顶点。问题是我必须做V DFS,其中V是顶点的数量。 (V最高可达10 ^ 5)。有没有更有效的方法来做到这一点?一些伪代码或实现将是值得赞赏的。

考虑这个图:(1 - > 3),(2 - > 3),(3 - > 1)

从1到2没有路径,但是从2到1(2 - > 3 - > 1)的路径。所以这意味着即使没有路径(v - > u),每对顶点(u - > v)都有一条路径。

3 个答案:

答案 0 :(得分:2)

查看Tarjan的强连接组件算法。如果只存在一个强连通分量,则意味着每对顶点之间存在一条路径。

要弄清楚这一点,请对图形进行拓扑排序,然后以反向伪拓扑顺序遍历它。如果您不需要重启'遍历这意味着,这意味着每个可能的顶点之间都存在一条路径。

答案 1 :(得分:1)

要查找是否有单个路径访问有向图的所有顶点(可以多次访问顶点和边),那么:

  1. 找到图表的strongly connected components [SCC]。
  2. 使用单个"伪顶点"减少替换每个SCC的图形。并包括连接SCC的边缘。
  3. 图形现在不包含循环(因为每个循环都是SCC的一部分)所以将是一个有根的图形/树,必须有:
    • 一个或多个根伪顶点(没有入站边);
    • 一个或多个叶子伪顶点(没有出站边缘;它可以同时是叶子和根顶点);和
    • 零或多个伪顶点,它们是分支的一部分(包括入站和出站边缘)。
  4. 平凡地说,每个叶子和一个分支的一部分都可以从祖先伪顶点到达(因为它们有入站边缘)但是不可能从另一个并行分支到达一个分支,所以我们只需要考虑结果graph是一个没有分支的简单路径。
  5. 计算根顶点的数量:
    • 如果存在单个根伪顶点(SCC),那么该SCC中包含的任何顶点都可以到达图中的所有其他顶点;
    • 如果有超过1个根伪顶点,则没有顶点具有到所有其他顶点的路径(因为您无法从不同的根到达一个根)。
  6. 如果奇异根伪顶点和每个后续后代伪顶点只有一个出站边(即没有分支),直到到达叶子,那么结果图包含一个可以到达所有顶点的路径。 / LI>

    <强>实施例

    如果图形的格式为:

    ,则将SCC缩减为伪顶点
    (1) -> (2) -> ... (n-1) -> (n)
    

    然后有一条路径可以访问所有顶点。

    如果是以下形式:

    (1_a) --\
             +--> (2) -> ... (n-1) -> (n)
    (1_b) --/
    

    然后无法从(1_a)到达顶点(1_b),反之亦然,因此没有可以到达所有顶点的路径。

    类似地:

                        /-> (n_a)
    (1) -> (2) -> ... -+
                        \-> n_b
    

    然后无法从(n_a)到达顶点(n_b),反之亦然,因此没有可以到达所有顶点的路径。

    最后,如果是形式:

                        /-> (x_a) -\
    (1) -> (2) -> ... -+            +-> ... (n-1) -> (n)
                        \-> (x_b) -/
    

    然后没有可以同时到达(x_a)(x_b)的路径。

答案 2 :(得分:0)

我不知道为什么有些答案看起来如此不必要地复杂。实际上,您可以仅使用图的拓扑排序,并检查是否存在连接每个节点及其后续节点的边。