所以,我试图在有向图中使用DFS找到一个循环。现在,我知道如果图形的拓扑排序不可能,那么图形包含一个循环。我为拓扑排序做了以下算法。我不确定在哪里修改此代码以便return 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)
我应该在哪里添加此检查以包含循环?
谢谢!
答案 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,您已检测到一个循环! (它被“探索”,这被称为前沿,而这里没有进一步的兴趣)。
注意,这可以集成到拓扑排序算法中 (我建议在科尔曼看一下这个。)