使用深度优先搜索查找图形中的循环

时间:2013-08-25 11:12:35

标签: algorithm graph depth-first-search

鉴于以下深度优先搜索,为什么ProcessEdge方法中的检查if(Parent[currVertex] != successorVertex)检测到一个循环?该代码遵循S.Skiena的Algortim Design Manual一书中给出的算法。支票可能是拼写错误,可能是if(Parent[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*/
        }
    }

更新

在勘误http://www.cs.sunysb.edu/~skiena/algorist/book/errata中找到对此代码的更正。参见(*)第173页,process_edge过程 - 正确的测试应该是

if (discovered[y] && (parent[x] != y)) { /* found back edge */

但这会检测周期吗? if检查永远不会通过,因为在DFS方法中,process_edge仅在discovered[y] == false时调用。

1 个答案:

答案 0 :(得分:1)

与Skiena的原始代码相比,您发布的代码存在显着差异:bfs-dfs.cfindcycle.c以及the rest。 Skiena的代码是错误的(尝试图3 2 1 2 2 3,一条双边路径),所以也许将其音译成Java的人尝试了一些修复。不幸的是,修复后的版本似乎也有错误,但如果没有完整的程序,我无法确定。

我相信您突出显示的行的意图如下。对于无向图表中的深度优先搜索,有两种类型的边,返回。当且仅当存在后沿时,该图具有循环。现在,Skiena选择的无向图的表示是将每个无向边存储为两个有向弧,每个方向一个。如果我们使用深度优先搜索来检测该有向图中的周期,那么由对应于单个无向边的两个有向弧组成的长度 - 两个周期被错误地报告为周期。如上所述,检查确保候选后弧[{1}}不与树弧y->x相反。