DFS:访问,访问和未访问混淆

时间:2017-02-22 19:24:19

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

来自Leetcode discussions的以下代码。

public class Solution {
    public boolean validTree(int n, int[][] edges) {
        int[] visited = new int[n];
        List<List<Integer>> adjList = new ArrayList<>();
        for (int i=0; i<n; ++i) { adjList.add(new ArrayList<Integer>()); }
        for (int[] edge: edges) {
            adjList.get(edge[0]).add(edge[1]);
            adjList.get(edge[1]).add(edge[0]);
        }
        if (hasCycle(-1, 0, visited, adjList)) { return false; }  // has cycle
        for (int v: visited) { if (v == 0) { return false; } }  // not 1 single connected component
        return true;
    }

    private boolean hasCycle(int pred, int vertex, int[] visited, List<List<Integer>> adjList) {
        visited[vertex] = 1;  // current vertex is being visited
        for (Integer succ: adjList.get(vertex)) {  // successors of current vertex
            if (succ != pred) {  // exclude current vertex's predecessor
                if (visited[succ] == 1) { return true; }  // ###back edge/loop detected!
                else if (visited[succ] == 0) {
                    if (hasCycle(vertex, succ, visited, adjList)) { return true; }
                }
            }
        }
        visited[vertex] = 2;
        return false;
    }
}

我的问题是:

1,对于DFS中的if (visited[succ] == 1) { return true; } // back edge/loop detected!,我尝试了visited[succ] == 1visited[succ] >= 1,所有这些都有效。 我很困惑``visit [succ] == 1 and访问过[succ] == 2```之间的区别是什么?他们可以检测到不同类型的圈子吗?

2,似乎如果我们使用visited存储True和False(已访问和未访问),它仍然有效(来自另一个Leetcode topic)。 我们什么时候应该使用未访问,访问,访问?什么时候我们应该使用未访问,并访问?任何例子?

由于

1 个答案:

答案 0 :(得分:1)

切换到visited[succ] >= 1不会产生等效算法:当前算法将检测定向非循环图(DAG),而修改后的算法将仅检测树(所有树都是DAG,但并非所有DAG都是树)

该算法使用2来允许DAG检测。如果您只需要树检测,则可以切换到使用布尔值;但是,对于DAG而言,仅仅标记所访问的顶点已经不够了。考虑这个简单的图表:

DAG

如果您将visited["C"]留在1,算法会在尝试A - >时报告一个周期。 C边缘。