1 25 39 package org.jgrapht.alg; 40 41 import java.util.*; 42 43 import org.jgrapht.*; 44 import org.jgrapht.graph.*; 45 46 47 62 public class StrongConnectivityInspector<V, E> 63 { 64 65 67 private final DirectedGraph<V, E> graph; 69 70 private LinkedList<VertexData<V>> orderedVertices; 72 73 private List<Set<V>> stronglyConnectedSets; 75 76 private List<DirectedSubgraph<V, E>> stronglyConnectedSubgraphs; 78 79 private Map<V, VertexData<V>> vertexToVertexData; 81 82 84 91 public StrongConnectivityInspector(DirectedGraph<V, E> directedGraph) 92 { 93 if (directedGraph == null) { 94 throw new IllegalArgumentException ("null not allowed for graph!"); 95 } 96 97 graph = directedGraph; 98 vertexToVertexData = null; 99 orderedVertices = null; 100 stronglyConnectedSets = null; 101 stronglyConnectedSubgraphs = null; 102 } 103 104 106 111 public DirectedGraph<V, E> getGraph() 112 { 113 return graph; 114 } 115 116 122 public boolean isStronglyConnected() 123 { 124 return stronglyConnectedSets().size() == 1; 125 } 126 127 135 public List<Set<V>> stronglyConnectedSets() 136 { 137 if (stronglyConnectedSets == null) { 138 orderedVertices = new LinkedList<VertexData<V>>(); 139 stronglyConnectedSets = new Vector<Set<V>>(); 140 141 createVertexData(); 143 144 Iterator<VertexData<V>> iter = 147 vertexToVertexData.values().iterator(); 148 149 while (iter.hasNext()) { 150 VertexData<V> data = iter.next(); 151 152 if (!data.discovered) { 153 dfsVisit(graph, data, null); 154 } 155 } 156 157 DirectedGraph<V, E> inverseGraph = 159 new DefaultDirectedGraph<V, E>(graph.getEdgeFactory()); 160 Graphs.addGraphReversed(inverseGraph, graph); 161 162 resetVertexData(); 164 165 iter = orderedVertices.iterator(); 169 170 while (iter.hasNext()) { 171 VertexData<V> data = iter.next(); 172 173 if (!data.discovered) { 174 Set<V> set = new HashSet<V>(); 176 stronglyConnectedSets.add(set); 177 dfsVisit(inverseGraph, data, set); 178 } 179 } 180 181 orderedVertices = null; 183 vertexToVertexData = null; 184 } 185 186 return stronglyConnectedSets; 187 } 188 189 202 public List<DirectedSubgraph<V, E>> stronglyConnectedSubgraphs() 203 { 204 if (stronglyConnectedSubgraphs == null) { 205 List<Set<V>> sets = stronglyConnectedSets(); 206 stronglyConnectedSubgraphs = 207 new Vector<DirectedSubgraph<V, E>>(sets.size()); 208 209 Iterator<Set<V>> iter = sets.iterator(); 210 211 while (iter.hasNext()) { 212 stronglyConnectedSubgraphs.add( 213 new DirectedSubgraph<V, E>( 214 graph, 215 iter.next(), 216 null)); 217 } 218 } 219 220 return stronglyConnectedSubgraphs; 221 } 222 223 228 private void createVertexData() 229 { 230 vertexToVertexData = 231 new HashMap<V, VertexData<V>>(graph.vertexSet().size()); 232 233 Iterator<V> iter = graph.vertexSet().iterator(); 234 235 while (iter.hasNext()) { 236 V vertex = iter.next(); 237 vertexToVertexData.put( 238 vertex, 239 new VertexData<V>(null, vertex, false, false)); 240 } 241 } 242 243 249 private void dfsVisit( 250 DirectedGraph<V, E> graph, 251 VertexData<V> vertexData, 252 Set<V> vertices) 253 { 254 Stack<VertexData<V>> stack = new Stack<VertexData<V>>(); 255 stack.push(vertexData); 256 257 while (!stack.isEmpty()) { 258 VertexData<V> data = stack.pop(); 259 260 if (!data.discovered) { 261 data.discovered = true; 262 263 if (vertices != null) { 264 vertices.add(data.vertex); 265 } 266 267 stack.push(new VertexData<V>(data, null, true, true)); 268 269 Iterator<? extends E> iter = 271 graph.outgoingEdgesOf(data.vertex).iterator(); 272 273 while (iter.hasNext()) { 274 E edge = iter.next(); 275 VertexData<V> targetData = 276 vertexToVertexData.get(this.graph.getEdgeTarget(edge)); 277 278 if (!targetData.discovered) { 279 stack.push(targetData); 281 } 282 } 283 } else if (data.finished) { 284 if (vertices == null) { 285 orderedVertices.addFirst(data.finishedData); 286 } 287 } 288 } 289 } 290 291 294 private void resetVertexData() 295 { 296 Iterator<VertexData<V>> iter = vertexToVertexData.values().iterator(); 297 298 while (iter.hasNext()) { 299 VertexData<V> data = iter.next(); 300 data.discovered = false; 301 data.finished = false; 302 } 303 } 304 305 307 310 private static final class VertexData<V> 311 { 312 private final VertexData<V> finishedData; 315 private final V vertex; 316 private boolean discovered; 317 private boolean finished; 318 319 private VertexData( 320 VertexData<V> finishedData, 321 V vertex, 322 boolean discovered, 323 boolean finished) 324 { 325 this.finishedData = finishedData; 326 this.vertex = vertex; 327 this.discovered = discovered; 328 this.finished = finished; 329 } 330 } 331 } 332 | Popular Tags |