// recursive DFS to detect cycles public boolean hasCycle() { // firstly check if this node is a visited clean node // this pre-check will avoid repeat search and save time if (cleanNode) { return false; } // if our curr node is a visited node, then it means we got a back edge in current path, so // there is a cycle if (visited) { return true; } // mark visited in current search visited = true; // check its neighbor nodes for (Node node : nodes) { // recursivly search each next node if (node.hasCycle()) { return true; } } // reset node as unvisited to avoid the impact on next search visited = false; // if there is no cycle in this node, we will set it as cleanNode cleanNode = true; return false; }
private boolean hasCycle(StringBuilder sb) { // we need put the root node first. To be convenient we want start DFS from any node, not the // node // without prerequisites or with most prerequisites. So we will build the string backward. // We will start build the string after we reach the bottom (the root node). Therefore, in DFS // we should use "depends on" relation, where we put root node to the bottom // cleanNode check first, so we can set and reset "visited" freely if (cleanNode) return false; if (visited) return true; visited = true; for (Node node : nodes) { if (node.hasCycle(sb)) return true; } cleanNode = true; visited = false; sb.append(c); return false; }
public boolean canFinish(int numCourses, int[][] prerequisites) { // create a node list, so we can visit node easier Node[] nodes = new Node[numCourses]; // initialize each node for (int i = 0; i < nodes.length; i++) { nodes[i] = new Node(); } // update neighbors of each node for (int[] pair : prerequisites) { nodes[pair[0]].addNode(nodes[pair[1]]); } // scan array to check if there is any cycle for (Node node : nodes) { if (node.hasCycle()) return false; } return true; }
static void solve_automata_to(Node state) { PriorityQueue<Node> queue = new PriorityQueue<Node>(N); queue.add(state); state.clear(); state.visited = false; Node current = null; String min = null; String max = null; boolean found = false; while (!queue.isEmpty()) { current = queue.poll(); if (!FINITE && current == FIRST) return; current.visited = true; current.iterator = 0; for (int i = 0; i < M; i++) { char c = (char) ('a' + i); min = c + current.min.data; max = c + current.max.data; for (Integer j : current) { state = states[j]; found = false; if (FINITE) { if (current.hasCycle) { if (!state.hasCycle) { state.hasCycle = true; found = true; } } else if (state.max.length <= current.max.length + 1) { if (state.max.length == current.max.length + 1) { if (max.compareTo(state.max.data) > 0) { found = true; state.max.length = current.max.length + 1; state.max.data = max; state.predecessor = current.index; } } else { state.predecessor = current.index; found = true; if (state.visited) { Node v = states[state.predecessor]; int curLength = current.max.length; while (state != v && curLength != state.max.length) { v = states[v.predecessor]; curLength--; } if (state == v) { state.hasCycle = true; current.hasCycle = true; queue.add(current); } } state.max.length = current.max.length + 1; state.max.data = max; } } } if (state.visited) { if (found) queue.add(state); continue; } if (state.min.length >= current.min.length + 1) { if (state.min.length == current.min.length + 1) { if (min.compareTo(state.min.data) < 0) { state.min.length = current.min.length + 1; state.min.data = min; found = true; } } else { state.min.length = current.min.length + 1; state.min.data = min; found = true; } } if (found) queue.add(state); } } } }