Side Topic: 如何在图中判断是否有环

有向图

  • bfs拓扑排序(always covered)

  • dfs markVisiting Two

    • 对点的状态分类增加

    • visited & unVisited VS visited & unVisited& visiting

  • Union Find

    • see previous

    • union 到两个已经同样老大的点

enum State {
    UNVISITED, VISITED, VISITTING;
}
class Node{
    int id;
    State state;
    List<Node> neighbors;
    public Node(int id) {
        this.id = id;
        this.state = State.UNVISITED;
    }
    // this class already overridden the util method 
    // such as hashCode(), equals(), toString();
}
// teturn type:是不是从这个点出发可以发现一个环
public boolean DFSMarkVisitedTwo(Node cur) {
    if (cur.state == State.VISITED) {
        return false; //理解:上次来这个点都没有找到环,这次来不用来了肯定也找不到
    }
    if (cur.state == State.VISITING) {
        //理解:你其实是在到达cur以后,在沿着边的顺序防伪cur的neighbor的过程中居然又回到了cur
        System.out.println("Cycle Detected");
        return true;
    }
    // 理解:现在cur的state一定是unvisited
    cur.state = State.VISITING:
    for (Node nei : cur.neighbors) {
        if (DFSMarkVisited(nei) == true) {
            //理解:从我某一个neighbor出发能找到环,那就说明这个图里面有环,不用再看我的其他neighbor了
                return true;
        }
    }
    cur.state = VISITED;
    // 理解:说明从我出发肯定没有环
    return false;
}

In real practice

private static final int UNISITTED = 0;
private static final int VISITING = 1;
private static final int vISITED = 2;

无向图

  • XXXXXbfs拓扑排序(always covered)

  • Union Find

    • see previous

    • union 到两个已经同样老大的点

  • dfs markVisiting One Modified:

    • 沿着一个方向走,不回头,如果你能走到一个走过的点

如果是非联通图,从每个联通块出发就好了

public void DFSMarkVisitedOneModified(Node start) {
    Set<Node> visited = new HashSet<>();
    return DFSModified(start, null, visited);
}
private boolean DFSModified(Node cur, Node prevNode, Set<Node> visited) {
    if (visited.contains(cur)) {
        System.out.println("There is a cycle");
        return true;
    }
    visited.add(cur);
    for (Node nei: cur.neighbors) {
        if (!nei.equals(prevNode)) {
            if (DFSModified(nei, cur, visited)) {
                return true;
            }
        }
    }
    return false;
}

Last updated