因此,我为DFS编写了以下代码:
void dfs (graph * mygraph, int foo, bool arr[]) // here, foo is the source vertex
{
if (arr[foo] == true)
return;
else
{
cout<<foo<<"\t";
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
if (arr[k] == false)
{
//cout<<k<<"\n";
dfs(mygraph,k,arr);
//cout<<k<<"\t";
}
it++;
}
}
//cout<<"\n";
}
现在,我读到,在一个无向图中,如果当DFS时,它再次返回到同一个顶点,有一个循环。所以我做的是这样,,
bool checkcycle( graph * mygraph, int foo, bool arr[] )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
result = checkcycle(mygraph,k,arr);
it++;
}
}
return result;
}
但是,我的检查周期函数返回true,即使他们没有周期。那是为什么呢?我的功能有问题吗?没有执行问题,否则我早就调试了,但他们似乎在我的逻辑中有问题。
在检查周期开始之前,arr[]中的所有bools都设置为false吗?
您确定节点的迭代器没有在已经遍历的边上加倍(从而多次看到起始节点,而不考虑循环)?
请注意,您的函数并不像您认为的那样。让我来看看这里发生了什么。假设以下关系:(1,2)、(1,3)、(2,3)。我并没有假设反射性(即,(1,2)并不意味着(2,1))。关系是定向的。
您需要一堆已访问的节点,或者只搜索原始节点。堆栈也将检测子循环(不包括原始节点的循环),但它也会占用更多内存。
编辑:节点堆栈不仅仅是一堆true
/false
值,而是节点编号的堆栈。当前堆栈跟踪中已访问的节点(如果该节点存在于堆栈中)。
然而,还有一种更有利于内存的方法:在调用结束时设置arr[foo]=false;
。像这样的东西:
bool checkcycle( graph * mygraph, int foo, bool arr[], int previousFoo=-1 )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
// This should prevent going back to the previous node
if (k != previousFoo) {
result = checkcycle(mygraph,k,arr, foo);
}
it++;
}
// Add this
arr[foo] = false;
}
return result;
}
我想应该够了。
编辑:现在应该支持无向图。节点:此代码未测试
编辑:有关详细的解决方案,请参见强连接组件
编辑:尽管在评论中给出了具体的解决方案,但这个答案是市场所接受的。阅读评论了解详细信息。
请告诉我为什么这段代码不能分析无向图中是否有循环?代码如下。这是Spoj上的PT07Y问题。我正在做的是取一个节点并执行dfs。当执行dfs时,如果我访问同一个节点,那么我说有一个循环。从一个节点执行dfs后,我使访问的数组为假,并为下一个节点执行,直到我得到一个周期或所有节点都被访问。
另一个问题只回答了如何检测一个周期,而不是输出它。所以,我想在一个无向图上写一个算法,在O(V+E)时间内运行BFS或DFS(V=顶点,E=边),如果有循环,则输出循环。 到目前为止,我所知道的是BFS/DFS是如何工作的,如果访问已经标记为已访问的节点,可以使用BFS检测周期。
目前我正在用这个样本进行拓扑排序,并对https://www.geeksforgeeks.org/topological-sorting/做了一些修改 我用它来排序要求解的变量的顺序。 样本 每个变量都有一个唯一整数,并存储在一个映射中 创建图形并添加边时,总共有4个顶点,因此我的代码将像这样构造图形 排序并按相反顺序得到结果后,它是正确的c 一切都很好,但我需要检测图中的循环引用。假设变量是 有
我有一个带边的无向图。每条边都具有一定的性质,如A点和B点之间的边之一是 在C点和D点之间的另一个可以是 我们得到了这样一个图和已知的旅行路径 有快一点的吗?
假设我有一个有V节点和E边的无向图。如果我用邻接列表表示图形,如果我有x和y之间边的表示,我还必须在邻接列表中有y和x之间边的表示。 我知道有向图的DFS具有VE复杂性。对于无向图,它没有v 2*e复杂性,因为您访问每个边2次?抱歉,如果这是一个愚蠢的问题...我真的很想明白这个想法。谢谢你,
我看到了这篇SO帖子,其中建议在有向图中使用DFS进行循环检测由于回溯而更快。这里我引用该链接: 深度优先搜索比广度优先搜索更节省内存,因为您可以更快地回溯。如果使用调用堆栈,则实现起来也更容易,但这取决于不溢出堆栈的最长路径。 如果你的图是有方向的,那么你不仅要记住你是否访问过一个节点,还要记住你是如何到达的。否则,你可能会认为你已经找到了一个循环,但在现实中,你所拥有的只是两条不同的路径- 为