当前位置: 首页 > 知识库问答 >
问题:

如何检测无向图是否有循环并用BFS或DFS输出

高勇
2023-03-14

另一个问题只回答了如何检测一个周期,而不是输出它。所以,我想在一个无向图上写一个算法,在O(V+E)时间内运行BFS或DFS(V=顶点,E=边),如果有循环,则输出循环。

到目前为止,我所知道的是BFS/DFS是如何工作的,如果访问已经标记为已访问的节点,可以使用BFS检测周期。

共有1个答案

冯枫涟
2023-03-14

要用DFS检测和输出一个循环,只需在到达时标记每个顶点;如果标记了当前顶点的任何子节点,那么您就知道您有一个涉及该子节点的循环。此外,您知道该子顶点是DFS遇到的属于这个特定循环的第一个顶点,并且DFS中自第一次遇到该顶点以来的每一次移动(即,从那以后尚未返回的每一次递归调用)都访问了循环中的另一个顶点。唯一需要向调用堆栈中传递的信息是这个子顶点,或者指示未找到循环的特殊值。您可以将其作为返回值传回:

dfs(v, p) {
    marked[v] = true
    For each neighbour u of v:
        If u != p:   # I.e. we ignore the edge from our parent p
            If marked[u]:
                Append v to cycleVertices
                Return u   # Cycle!
            Else:
                result = dfs(u, v)
                If result == FINISHED:
                    # Some descendant found a cycle; now we're just exiting
                    Return FINISHED
                Else if result != NOCYCLE:
                    # We are in a cycle whose "top" vertex is result.
                    Append v to cycleVertices
                    If result == v:
                        return FINISHED   # This was the "top" cycle vertex
                    Else:
                        return result     # Pass back up

    marked[v] = false    # Not necessary, but (oddly?) not harmful either ;)
    Return NOCYCLE
}

对某个顶点r调用DFS(r,nil)(以及任何非顶点值nil)后,如果找到循环,则将用循环填充CycleVertices

[编辑:正如Juan Lopes所指出的,没有标记顶点是不必要的,而且可能会使人困惑;但有趣的是,这并不影响无向图的时间复杂度。]

 类似资料:
  • 因此,我为DFS编写了以下代码: 现在,我读到,在一个无向图中,如果当DFS时,它再次返回到同一个顶点,有一个循环。所以我做的是这样,, 但是,我的检查周期函数返回true,即使他们没有周期。那是为什么呢?我的功能有问题吗?没有执行问题,否则我早就调试了,但他们似乎在我的逻辑中有问题。

  • 目前我正在用这个样本进行拓扑排序,并对https://www.geeksforgeeks.org/topological-sorting/做了一些修改 我用它来排序要求解的变量的顺序。 样本 每个变量都有一个唯一整数,并存储在一个映射中 创建图形并添加边时,总共有4个顶点,因此我的代码将像这样构造图形 排序并按相反顺序得到结果后,它是正确的c 一切都很好,但我需要检测图中的循环引用。假设变量是 有

  • 我看到了这篇SO帖子,其中建议在有向图中使用DFS进行循环检测由于回溯而更快。这里我引用该链接: 深度优先搜索比广度优先搜索更节省内存,因为您可以更快地回溯。如果使用调用堆栈,则实现起来也更容易,但这取决于不溢出堆栈的最长路径。 如果你的图是有方向的,那么你不仅要记住你是否访问过一个节点,还要记住你是如何到达的。否则,你可能会认为你已经找到了一个循环,但在现实中,你所拥有的只是两条不同的路径- 为

  • 你有一辆2005年本田雅阁,油箱里还剩50英里(最大重量)。在50英里半径范围内,你可以访问哪些麦当劳的位置(图节点)?这是我的问题。 如果你有一个加权有向无环图,你如何找到在给定的权限制内可以访问的所有节点? 我知道Dijkstra的算法,但我似乎找不到任何关于它在最小路径问题之外的用途的文档。在我的例子中,我们没有特别想结束的节点,我们只想在不超过最大权重的情况下尽可能多地结束。似乎您应该能够

  • 我试图用BFS算法在有向图中检测循环。我检测周期的主要想法是:由于BFS只访问每个节点(和边缘)一次,如果我再次遇到已访问的节点;它会导致一个循环。然而,我的代码有时会找到循环,有时不会。 我从维基百科修改的伪代码如下: 我错过了什么?

  • 我在这里读到一篇关于在有向图中求圈的讨论。现在,OP声称我们需要验证两件事: 从到有一个后沿 在递归堆栈中 为什么我们需要第二次测试?你能举个例子来说明它的必要性吗?