Algorithm 使用深度优先搜索查找图中的圈

Algorithm 使用深度优先搜索查找图中的圈,algorithm,graph,depth-first-search,Algorithm,Graph,Depth First Search,鉴于以下深度优先搜索,为什么ProcessEdge方法中的检查如果(父[currVertex]!=successorVertex)检测到循环?该代码遵循S.Skiena在《算法设计手册》一书中给出的算法。检查可能是打字错误,如果(父[successorVertex]!=currVertex),则该检查可能是。请要求任何澄清。我真的被这件事难住了 public void Search(int start) { /* NOTE: the differences fro

鉴于以下深度优先搜索,为什么ProcessEdge方法中的检查
如果(父[currVertex]!=successorVertex)
检测到循环?该代码遵循S.Skiena在《算法设计手册》一书中给出的算法。检查可能是打字错误,如果(父[successorVertex]!=currVertex),则该检查可能是
。请要求任何澄清。我真的被这件事难住了

    public void Search(int start)
    {
        /* NOTE: the differences from BFS are: this uses a stack instead of a queue AND this maintains 'time' variable */
        Stack<int> s = new Stack<int>();
        int currVertex;
        int successorVertex;
        int time = 0;

        s.Push(start);

        Discovered[start] = true;

        while (s.Count != 0)
        {
            currVertex = s.Pop();
            // time increments every time we enter a node (when discovered) and every time we exit a node (when processed_late, i.e. when all its neighbours have been processed)
            time++;
            EntryTime[currVertex] = time;

            ProcessVertexEarly(currVertex);
            Processed[currVertex] = true;

            for (int i = 0; i < Graph.Vertices[currVertex].Count; i++)
            {
                successorVertex = Graph.Vertices[currVertex][i].Y;
                if (!Processed[successorVertex] || Graph.IsDirected)
                {
                    ProcessEdge(currVertex, successorVertex);
                }
                if (!Discovered[successorVertex])
                {
                    s.Push(successorVertex);
                    Discovered[successorVertex] = true;
                    Parent[successorVertex] = currVertex;
                }
            }
            // time increments every time we enter a node (when discovered) and every time we exit a node (when processed_late, i.e. when all its neighbours have been processed)
            time++;
            ExitTime[currVertex] = time;
            ProcessVertexLate(currVertex);
        }
    }

    private void ProcessEdge(int currVertex, int successorVertex)
    {
        if(Parent[currVertex] != successorVertex) // then we've found a cycle
        {
            /* Found cycle*/
        }
    }

但这会检测周期吗??if检查将永远不会通过,因为在DFS方法中,只有当
发现[y]==false
时才会调用
进程边缘
,您发布的代码与Skiena的原始代码相比有显著差异:和。Skinena的代码有缺陷(请尝试图3 2 1 2 3,一个两条边的路径),因此可能将其翻译成Java的人尝试了一些修复。不幸的是,修复后的版本似乎也有缺陷,尽管我不能确定没有完整的程序


我相信你强调的这条线的意图如下。对于无向图中的深度优先搜索,有两种类型的边:树边和后向边。图有一个循环当且仅当存在后边时。现在,Skiena选择的无向图的表示是将每个无向边存储为两个有向弧,每个方向一个。如果我们使用深度优先搜索来检测这个有向图中的圈,那么由对应于单个无向边的两个有向弧组成的两个圈的长度将被错误地报告为圈。如前所述,该检查确保候选弧
y->x
不是树弧
x->y

的反方向。您上面提到的图形是否被解释为:顶点0连接到顶点3,顶点1连接到顶点2,顶点2连接到顶点1等等?另外,您能推荐一种更好的存储图形的方法吗?Thanks@bytefire3个顶点,2条边,第一条边1-2,第二条边2-3。Skiena的代码的问题是它调用树边上的
process\u edge
。@bytefire Skiena的表示法是存储简单无向图的好方法。我现在明白了!在没有圈的无向图中,任何顶点最多有一个父节点。在第二轮(即反弧)处理边时,如果起始顶点的父顶点与结束顶点不同,则我们有一个循环。谢谢你的帮助。顺便说一句,我将代码从C翻译成C,但在书中没有使用递归版本。我将BFS代码中的队列替换为堆栈。尚未测试,因此可能存在其他错误。重新更新:如果未发现或未处理
y
,则Skiena的
dfs
调用
process\u edge
。在探索离开顶点的每条边之前,顶点不会被标记为已处理。
if (discovered[y] && (parent[x] != y)) { /* found back edge */