/* * The subroutine of DFS. NOTE: the set is used to distinguish between 1st * and 2nd round of DFS. set == null: finished vertices are stored (1st * round). set != null: all vertices found will be saved in the set (2nd * round) */ private void dfsVisit( DirectedGraph<V, E> visitedGraph, VertexData<V> vertexData, Set<V> vertices) { Deque<VertexData<V>> stack = new ArrayDeque<VertexData<V>>(); stack.add(vertexData); while (!stack.isEmpty()) { VertexData<V> data = stack.removeLast(); if (!data.isDiscovered()) { data.setDiscovered(true); if (vertices != null) { vertices.add(data.getVertex()); } stack.add(new VertexData1<V>(data, true, true)); // follow all edges for (E edge : visitedGraph.outgoingEdgesOf(data.getVertex())) { VertexData<V> targetData = vertexToVertexData.get(visitedGraph.getEdgeTarget(edge)); if (!targetData.isDiscovered()) { // the "recursion" stack.add(targetData); } } } else if (data.isFinished()) { if (vertices == null) { orderedVertices.addFirst(data.getFinishedData()); } } } }
/** * Computes a {@link List} of {@link Set}s, where each set contains vertices which together form a * strongly connected component within the given graph. * * @return <code>List</code> of <code>Set</code> s containing the strongly connected components */ public List<Set<V>> stronglyConnectedSets() { if (stronglyConnectedSets == null) { orderedVertices = new LinkedList<VertexData<V>>(); stronglyConnectedSets = new Vector<Set<V>>(); // create VertexData objects for all vertices, store them createVertexData(); // perform the first round of DFS, result is an ordering // of the vertices by decreasing finishing time for (VertexData<V> data : vertexToVertexData.values()) { if (!data.isDiscovered()) { dfsVisit(graph, data, null); } } // 'create' inverse graph (i.e. every edge is reversed) DirectedGraph<V, E> inverseGraph = new EdgeReversedGraph<V, E>(graph); // get ready for next dfs round resetVertexData(); // second dfs round: vertices are considered in decreasing // finishing time order; every tree found is a strongly // connected set for (VertexData<V> data : orderedVertices) { if (!data.isDiscovered()) { // new strongly connected set Set<V> set = new HashSet<V>(); stronglyConnectedSets.add(set); dfsVisit(inverseGraph, data, set); } } // clean up for garbage collection orderedVertices = null; vertexToVertexData = null; } return stronglyConnectedSets; }
/* * Resets all VertexData objects. */ private void resetVertexData() { for (VertexData<V> data : vertexToVertexData.values()) { data.setDiscovered(false); data.setFinished(false); } }