/** * Recursive part of tarjans algorithm to find strongly connected components. Algorithm is e.g. * described in <a * href="http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm">wikipedia</a> * * @param maxdfs The current value for maxdfs. * @param v The current Node to process. * @param workset Set of all unreached Nodes. * @param stack Temporary datastructure for algorithm. * @param nodeStrMap Because the sccs are returned as a list of variables (i.e. Strings), the * mapping from Node to String must be given. * @param sccs All found strongly connected components are added to this list. * @return an updated value for maxdfs. */ private static int tarjan( int maxdfs, DirectedGraph.Node v, Set<DirectedGraph.Node> workset, LinkedList<DirectedGraph.Node> stack, Map<DirectedGraph.Node, String> nodeStrMap, List<List<String>> sccs) { v.dfs = maxdfs; v.lowlink = maxdfs; maxdfs++; stack.push(v); workset.remove(v); for (DirectedGraph.Node succ : v.getSuccessors()) { if (workset.contains(succ)) { maxdfs = tarjan(maxdfs, succ, workset, stack, nodeStrMap, sccs); v.lowlink = Math.min(v.lowlink, succ.lowlink); } else if (succ.dfs > 0) { // <==> stack.contains(succ) v.lowlink = Math.min(v.lowlink, succ.dfs); } } if (v.lowlink == v.dfs) { DirectedGraph.Node succ; LinkedList<String> scc = new LinkedList<>(); do { succ = stack.pop(); succ.dfs = -succ.dfs; scc.add(nodeStrMap.get(succ)); } while (!succ.equals(v)); if (scc.size() > 1) { sccs.add(scc); } } return maxdfs; }