// 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;
  }
Example #4
0
  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);
        }
      }
    }
  }