使用DFS在有向图中检测循环?

时间:2015-07-21 14:32:56

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

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

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)

我应该在哪里添加此检查以包含循环?

谢谢!

3 个答案:

答案 0 :(得分:11)

在有向图中查找循环的最简单方法如下:

使用三个顶点状态:“未探索”,“正在探索”和“充分探索”。当您输入新顶点时,将其设置为“正在探索”,当您完成顶点时,将其设置为“完全探索”。现在,当你迭代一些顶点的邻居时,如果你来到一个“正在探索”的顶点,那么就有一个循环。

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的拓扑排序运行并创建一些顶点排序。现在迭代所有边缘并检查它们是否正确定向。如果所有边缘都正确定向,那么如果没有循环,则存在至少一个。

答案 1 :(得分:3)

对于无向图,请按照以下步骤进行操作 -

1)取代布尔访问数组,使其为int类型,所有索引初始化为-1。

此处-1 = 未探索,0 = 正在探索,1 = 完全探索

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

此处true = 包含周期,false = 不包含周期

3)现在按如下方式编写DFS(以下是C ++代码) -

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;
}

答案 2 :(得分:1)

我建议阅读“算法 - 介绍”中的相应部分(Cormen等人)。

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

不是将顶点V标记为已探索/未探索,而是添加其他标签状态“current_explored”。 每个顶点在开头标记为未探测(如当下)。但它在你的DFS的第1步中被标记为“current_explored”(而不是被探索),并在你的DFS中的for-loop 2之后进行了标记。

在DFS中递归调用之前,请检查状态。如果它未被探索,只需递归调用(如当前)。如果它是current_explored,您已检测到一个循环! (它被“探索”,这被称为前沿,而这里没有进一步的兴趣)。

注意,这可以集成到拓扑排序算法中 (我建议在科尔曼看一下这个。)