C++ 如何找到是否存在';给定图的每对顶点之间有一条路径?

C++ 如何找到是否存在';给定图的每对顶点之间有一条路径?,c++,graph,graph-theory,depth-first-search,C++,Graph,Graph Theory,Depth First Search,为了找出有向图中每对顶点之间是否存在路径,我检查是否可以使用DFS从特定顶点访问所有顶点。问题是我必须做vdfs,其中V是顶点的数目。(V最多可为10^5)。有没有更有效的方法?一些伪代码或实现将不胜感激 考虑这个图:(1->3),(2->3),(3->1) 没有从1到2的路径,但是有一个从2到1的路径(2->3->1)。这意味着即使没有路径(v->u),每对顶点(u->v)都有一条路径。看看Tarjan的强连通组件算法。如果只有一个强连接组件存在,这意味着每对顶点之间都存在一条路径 为了解决这

为了找出有向图中每对顶点之间是否存在路径,我检查是否可以使用DFS从特定顶点访问所有顶点。问题是我必须做vdfs,其中V是顶点的数目。(V最多可为10^5)。有没有更有效的方法?一些伪代码或实现将不胜感激

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


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

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


为了解决这个问题,对图进行拓扑排序,然后以相反的伪拓扑顺序遍历它。如果不需要“重新启动”遍历,这意味着每个可能的顶点之间都存在一条路径。

要查找是否有一条路径访问有向图的所有顶点(可以多次访问顶点和边),请执行以下操作:

  • 找到图表的[SCC]
  • 减少图形,用单个“伪顶点”替换每个SCC,并包括连接SCC的边
  • 该图现在将不包含任何循环(因为每个循环都是SCC的一部分),因此将是一个根图/树,并且必须有:
    • 一个或多个根伪顶点(没有入站边)
    • 一个或多个叶伪顶点(没有出站边;可以同时是叶和根顶点);及
    • 作为分支一部分的零个或多个伪顶点(具有入站边和出站边)
  • 每一个叶和一个分支的一部分都可以从祖先伪顶点到达(因为它们有入边),但是不可能从另一个并行分支到达一个分支,所以我们只需要考虑得到的图是否是没有分支的简单路径。
  • 计算根顶点的数量:
    • 如果存在单根伪顶点(SCC),则该SCC中包含的任何顶点都可以到达图中的所有其他顶点
    • 如果有多个根伪顶点,则不存在指向所有其他顶点的路径的顶点(因为无法从不同的根到达一个根)
  • 如果单根伪顶点和每个后续子代伪顶点在到达叶之前只有一条出站边(即没有分支),则生成的图包含一条可以到达所有顶点的路径
  • 示例

    将SCC减少为伪顶点后,如果图形的形式为:

    (1) -> (2) -> ... (n-1) -> (n)
    
    (1_a) --\
             +--> (2) -> ... (n-1) -> (n)
    (1_b) --/
    
                        /-> (x_a) -\
    (1) -> (2) -> ... -+            +-> ... (n-1) -> (n)
                        \-> (x_b) -/
    
    然后有一条路径可以访问所有顶点

    如属以下形式:

    (1) -> (2) -> ... (n-1) -> (n)
    
    (1_a) --\
             +--> (2) -> ... (n-1) -> (n)
    (1_b) --/
    
                        /-> (x_a) -\
    (1) -> (2) -> ... -+            +-> ... (n-1) -> (n)
                        \-> (x_b) -/
    
    然后顶点
    (1_a)
    无法从
    (1_b)
    访问,反之亦然,因此没有可以访问所有顶点的路径

    同样地:

                        /-> (n_a)
    (1) -> (2) -> ... -+
                        \-> n_b
    
    然后,顶点
    (n_a)
    无法从
    (n_b)
    访问,反之亦然,因此没有可以访问所有顶点的路径

    最后,如果是表格:

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

    那么就没有一条路径可以同时到达
    (xu a)
    (xu b)

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

    这是有向图还是无向图?您可以检查图表是否包含多个强连接组件哦,对不起。我忘了提那个,但它是一个有向图。我会编辑它,然后你会寻找“如果每个顶点都可以从其他顶点到达,那么一个图就是强连通的”——我并不需要每个顶点都可以从其他顶点到达。我只想知道每一对都有一条从u到v或v到u的路径。在“每一对顶点之间必须存在一条路径”和“从每个顶点到所有其他顶点必须存在一条路径”之间有什么区别?我已经编辑了我的问题。我想在我举的图中有两个SCC,对吗?但无论如何,在所有顶点之间至少有一条路径。这实际上是可行的。现在我必须花一些时间来尝试实现这一点。。。谢谢@FernandoMussel感谢您的编辑建议-我考虑了您建议的另一个案例,并重新编辑了算法。