C++ 使用DFS检测有向图中的循环?

C++ 使用DFS检测有向图中的循环?,c++,algorithm,graph,depth-first-search,C++,Algorithm,Graph,Depth First Search,所以,我试图在有向图中找到一个使用DFS的循环。现在,我知道如果一个图的拓扑排序是不可能的,那么这个图包含一个圈。我为拓扑排序做了以下算法。我不确定应该在哪里修改这段代码以返回true或false,并检查我的图形是否包含循环。以下是我使用的算法: DFS-Loop (Graph G) 1. Mark all vertices as unexplored. 2. Set label = n // number of vertices 3. For each vertex V (belonging

所以,我试图在有向图中找到一个使用DFS的循环。现在,我知道如果一个图的拓扑排序是不可能的,那么这个图包含一个圈。我为拓扑排序做了以下算法。我不确定应该在哪里修改这段代码以返回true或false,并检查我的图形是否包含循环。以下是我使用的算法:

DFS-Loop (Graph G)

1. Mark all vertices as unexplored.
2. Set label = n // number of vertices
3. For each vertex V (belonging to) G
   -- If V not yet explored,
   -- DFS (G,V)
4. Set f(V) = current_label // here, f(V) is basically the position of V in the ordering
5. current_label-- 

Where DFS(G,V) will be something like: 

1. Mark V as explored.
2. For every vertex K belonging to Adj.(V)
   -- If K is not explored, 
   -- Call DFS(G,K)
对于是否包含循环,我应该在何处添加此检查


谢谢

在有向图中寻找圈的最简单方法如下

使用顶点的三种状态:未探索、正在探索和完全探索。输入新顶点时,将其设置为“正在探索”,使用完顶点后,将其设置为“完全探索”。现在,当你迭代某个顶点的邻域时,如果你到达一个正在探索的顶点,那么有一个循环

DFS(G,V):
1. Mark V as "being explored"
2. For every vertex K belonging to Adj.(V)
   -- If K is not explored, 
      -- Call DFS(G,K)
   -- else if K is "being explored" (not "fully explored")
      -- then there is a cycle
3. Mark V as "fully explored" 
通过从找到的正在探索的顶点回溯,可以找到循环


另一种方法是只允许基于DFS的拓扑排序运行并创建一些顶点排序。现在迭代所有边并检查它们是否正确定向。如果所有边都正确定向,那么如果没有圈,则至少有一个圈。

在有向图中查找圈的最简单方法如下所示

使用顶点的三种状态:未探索、正在探索和完全探索。输入新顶点时,将其设置为“正在探索”,使用完顶点后,将其设置为“完全探索”。现在,当你迭代某个顶点的邻域时,如果你到达一个正在探索的顶点,那么有一个循环

DFS(G,V):
1. Mark V as "being explored"
2. For every vertex K belonging to Adj.(V)
   -- If K is not explored, 
      -- Call DFS(G,K)
   -- else if K is "being explored" (not "fully explored")
      -- then there is a cycle
3. Mark V as "fully explored" 
通过从找到的正在探索的顶点回溯,可以找到循环


另一种方法是只允许基于DFS的拓扑排序运行并创建一些顶点排序。现在迭代所有边并检查它们是否正确定向。如果所有边都正确定向,则没有循环,否则至少有一个循环。

我建议阅读《算法-介绍Cormen等人》中的相应章节

基本上,当您重新访问未完成的顶点时,需要检测:

不将顶点V标记为已探测/未探测,而是添加当前已探测的附加标签状态。 每个顶点在开始时都标记为未探测,与在瞬间一样。但它在DFS的步骤1中标记为“当前已探索”,而不是在DFS的for循环2之后标记为“已探索”

在DFS中递归调用之前,请检查状态。如果它未被探测,只需像当前一样递归调用。如果当前正在探索,则表示您已检测到一个循环!据探索,这被称为前沿,在此不再感兴趣

注意,这可以集成到拓扑排序算法中
我建议在Cormen网站上也能找到这一点。

我建议阅读《算法-Cormen等人简介》中的相应章节

基本上,当您重新访问未完成的顶点时,需要检测:

不将顶点V标记为已探测/未探测,而是添加当前已探测的附加标签状态。 每个顶点在开始时都标记为未探测,与在瞬间一样。但它在DFS的步骤1中标记为“当前已探索”,而不是在DFS的for循环2之后标记为“已探索”

在DFS中递归调用之前,请检查状态。如果它未被探测,只需像当前一样递归调用。如果当前正在探索,则表示您已检测到一个循环!据探索,这被称为前沿,在此不再感兴趣

注意,这可以集成到拓扑排序算法中
我建议您也在Cormen中查找此图。

对于无向图,只需遵循以下步骤-

1而不是布尔数组,使其为int类型,所有索引初始化为-1

这里-1=未探索,0=正在探索,1=完全探索

2将全局布尔变量标志初始化为false

此处true=包含循环,false=不包含循环

3现在写DFS如下:C++代码-< /P>

void dfs(int s)
{
    visited[s] = 0;
    for(int i = 0; i < adj[s].size(); i++)
    {
        if(visited[ adj[s][i] ] == -1)
        {
            dfs(adj[s][i]);
        }
        else if(visited[adj[s][i]] == 1)
        {
            flag = true;
            return;
        }
    }
    visited[s] = 1;
}

对于无向图,只需执行以下步骤-

1而不是布尔数组,使其为int类型,所有索引初始化为-1

这里-1=未探索,0=正在探索,1=完全探索

2将全局布尔变量标志初始化为false

此处true=包含循环,false=不包含循环

3现在写DFS如下:C++代码-< /P>

void dfs(int s)
{
    visited[s] = 0;
    for(int i = 0; i < adj[s].size(); i++)
    {
        if(visited[ adj[s][i] ] == -1)
        {
            dfs(adj[s][i]);
        }
        else if(visited[adj[s][i]] == 1)
        {
            flag = true;
            return;
        }
    }
    visited[s] = 1;
}

visited[adj[s][i]]==1不正确。应访问[adj[s][i]==0,即当顶点正在移动时explored@suraznegi我写的算法是针对无向图的,在这种情况下,visited[adj[s][I]]==1是正确的。visited[adj[s][I]==1是不正确的,它应该访问[adj[s][I]==0,即当顶点
正在explored@suraznegi我写的算法是针对无向图的,在这种情况下,访问[adj[s][I]]==1是正确的。如果充分研究K,则应该是正确的。如果我使用2节点1边图,您的算法将失败。它会将其标记为有一个循环。@ManishSharma,请注意,如果完全探索了K,则该图为directedIt,应为else。如果我使用2节点1边图,您的算法将失败。它会将其标记为有一个循环。@ManishSharma,请注意,该图是有方向的