/** * Algorithm of Tarjan for computing the strongly connected components of a graph. * * @param v current node * @throws QueryException if a variable directly calls itself */ private void tarjan(final int v) throws QueryException { final int ixv = 2 * v, llv = ixv + 1, idx = next++; while (list.size() <= llv) list.add(-1); list.set(ixv, idx); list.set(llv, idx); stack.push(v); for (final int w : adjacentTo(v)) { final int ixw = 2 * w, llw = ixw + 1; if (list.size() <= ixw || list.get(ixw) < 0) { // Successor w has not yet been visited; recurse on it tarjan(w); list.set(llv, Math.min(list.get(llv), list.get(llw))); } else if (stack.contains(w)) { // Successor w is in stack S and hence in the current SCC list.set(llv, Math.min(list.get(llv), list.get(ixw))); } } // If v is a root node, pop the stack and generate an SCC if (list.get(llv) == list.get(ixv)) { int w; Scope[] out = null; do { w = stack.pop(); final Scope scp = scopes.get(w); out = out == null ? new Scope[] {scp} : Array.add(out, scp); } while (w != v); result.add(out); } }