import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
/**
* Directed Graph API
* @author Prateek
*/
class DiGraph {
protected int numVertices;
protected int numEdges;
//Map to maintain adjacency List
protected Map
<Integer,List
<Integer
>> adjList
; // Map to maintain visit status
protected Map
<Integer, Boolean
> vistedStatus
;
/*
* Constructor when number of vertices are not known
*/
public DiGraph() {
this.
adjList = new HashMap
<Integer,List
<Integer
>>(); this.
vistedStatus = new HashMap
<Integer, Boolean
>() ; }
/*
* Constructor when number of vertices are known
*/
public DiGraph(int V) {
this.numVertices = V;
this.
adjList = new HashMap
<Integer,List
<Integer
>>(V
); this.
vistedStatus = new HashMap
<Integer, Boolean
>(V
) ; }
/**
* Edge in a directed graph
*/
protected void addEdge(int src, int dest) {
List<Integer> list=adjList.get(src);
if(list==null)
list=new ArrayList<Integer>();
list.add(dest);
adjList.put(src,list);
vistedStatus.put(src, false); //visit status set to false
vistedStatus.put(dest, false);
}
/**
* DFS run on a given vertex
* @param vertex
*/
protected void dfsUtil(int vertex){
List <Integer
> list
= adjList.
get(vertex
) ;
vistedStatus.put(vertex, true) ;
System.
out.
print(vertex
+ "\t");
if(list!=null){
int size = list.size();
for(int i = 0;i < size ; i++){
int v=list.get(i);
if(!vistedStatus.get(v))
dfsUtil(v);
}
}
}
}
//------------------------------------------------------------------------------------
/**
* SCC for a direceted Graph
* @author Prateek
*/
class SCC extends DiGraph{
//Stack to hold finishing times i.e reverse post-order of DFS
private Stack<Integer> stack = new Stack<Integer>();
//Adjacency List to hold transpose Graph
private Map
<Integer,List
<Integer
>> reverseAdjList
;
/**Contructor
* If number of vertices is not given
*/
public SCC() {
this.
reverseAdjList = new HashMap
<Integer,List
<Integer
>>(numVertices
) ; }
/**
* Constructor: If number of vertices is given
*/
public SCC(int numVertices) {
super(numVertices);
this.
reverseAdjList = new HashMap
<Integer,List
<Integer
>>(numVertices
) ; }
/*=========Computes SCC Starts===================*/
/**
* Computes SCC, performs Kosaraju's Steps
*/
private void computeSCC(SCC g){
//Step1: Reverse Graph
//Transpose Graph
transpose(g);
Set
<Map.
Entry<Integer,Boolean
>> set
= vistedStatus.
entrySet(); Iterator
<Map.
Entry<Integer, Boolean
>> it
= set.
iterator();
//Step 2 : Fill Stack
//1st DFS on Reversed Graph
//Calcating Reverse Post order
while(it.hasNext()){
int vertex= entry.getKey();
boolean isVisited= entry.getValue();
if(!isVisited){
fillOrderStackDFS(vertex);
}
}
//Reset Visit Status
resetVisitStatus();
System.
out.
println("SCCs of Digraph: ");
//Step 3: Run DFS using the Stack
//2nd DFS on Original Graph
while(!stack.isEmpty()){
int poped=stack.pop();
if(!vistedStatus.get(poped))
{
System.
out.
println("==========================="); dfsUtil(poped);
}
}
System.
out.
println("==========================="); }
/*=============Reversing of Graph Starts================== */
/**
* Transpose given Graph, ie. reverse all the edges
* @param g
*/
private void transpose(SCC g){
Set
<Map.
Entry<Integer, Boolean
>> set
=vistedStatus.
entrySet(); Iterator
<Map.
Entry<Integer, Boolean
>> iterator
=set.
iterator();
while(iterator.hasNext())
{
int vertex=node.getKey();
List<Integer> list=adjList.get(vertex);
if(list!=null)
{
int size=list.size();
for(int i=0;i <size; ++i)
{
int adjNode=list.get(i);
g.addReverseEdge(vertex,adjNode);
}
}
}
}
/**
* Adding reverse edge compared to original graph,
* edge(dest-->src)
*/
private void addReverseEdge(int src, int dest) {
List<Integer> list=reverseAdjList.get(dest);
if(list==null)
list=new ArrayList<Integer>();
list.add(src);
reverseAdjList.put(dest,list);
}
/*=============Reversing of Graph Ends================== */
/* ============= Filling The Stack Starts ===============*/
/**
* Fill the stack to form reverse post-order using DFS
* @param vertex
*/
private void fillOrderStackDFS(int vertex){
vistedStatus.put(vertex, true);
List<Integer> list=reverseAdjList.get(vertex);
if(list!=null){
int size=list.size();
for(int i=0;i<size;i++){
int adjNode= list.get(i);
boolean isVisited = vistedStatus.get(adjNode);
if(!isVisited)
fillOrderStackDFS(adjNode);
}
}
stack.push(vertex); //Push the vertex when all connecting links processed
}
/* ============= Filling The Stack Ends ===============*/
/**
* Reset Visit Status of all vertices
*/
private void resetVisitStatus(){
for (Map.
Entry<Integer, Boolean
> entry
: vistedStatus.
entrySet()) entry.setValue(false);
}
public static void main
(String[] args
) { //Test Case1:
/*int numVertices = 5;
SCC g=new SCC(numVertices);
g.addEdge(1, 0);
g.addEdge(0, 2);
g.addEdge(2, 1);
g.addEdge(0, 3);
g.addEdge(3, 4);
g.computeSCC(g);*/
//Test Case2:
int numVertices = 11;
SCC g=new SCC(numVertices);
g.addEdge(1, 2);
g.addEdge(2, 3);
g.addEdge(3, 1);
g.addEdge(3, 4);
g.addEdge(3, 7);
g.addEdge(7, 4);
g.addEdge(4, 6);
g.addEdge(6, 7);
g.addEdge(4, 5);
g.addEdge(5, 6);
g.addEdge(4, 9);
g.addEdge(5, 8);
g.addEdge(8, 9);
g.addEdge(9, 10);
g.addEdge(10, 8);
g.addEdge(11, 10);
g.addEdge(11, 9);
g.addEdge(2, 11);
g.computeSCC(g);
}
}
aW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CmltcG9ydCBqYXZhLnV0aWwuU3RhY2s7Ci8qKgogKiBEaXJlY3RlZCBHcmFwaCBBUEkKICogQGF1dGhvciBQcmF0ZWVrCiAqLwogY2xhc3MgRGlHcmFwaCB7CgoJcHJvdGVjdGVkIGludCBudW1WZXJ0aWNlczsKCXByb3RlY3RlZCBpbnQgbnVtRWRnZXM7CgoJLy9NYXAgdG8gbWFpbnRhaW4gYWRqYWNlbmN5IExpc3QKCXByb3RlY3RlZCBNYXA8SW50ZWdlcixMaXN0PEludGVnZXI+PiBhZGpMaXN0OwoJLy8gTWFwIHRvIG1haW50YWluIHZpc2l0IHN0YXR1cwoJcHJvdGVjdGVkIE1hcDxJbnRlZ2VyLCBCb29sZWFuPiB2aXN0ZWRTdGF0dXM7CgoJLyoKCSAqIENvbnN0cnVjdG9yIHdoZW4gbnVtYmVyIG9mIHZlcnRpY2VzIGFyZSBub3Qga25vd24KCSAqLwoJcHVibGljIERpR3JhcGgoKSB7CgkJdGhpcy5hZGpMaXN0ID0gbmV3IEhhc2hNYXA8SW50ZWdlcixMaXN0PEludGVnZXI+PigpOwoJCXRoaXMudmlzdGVkU3RhdHVzID0gbmV3IEhhc2hNYXA8SW50ZWdlciwgQm9vbGVhbj4oKSA7IAoJfQoKCS8qCgkgKiBDb25zdHJ1Y3RvciB3aGVuIG51bWJlciBvZiB2ZXJ0aWNlcyBhcmUga25vd24KCSAqLwoJcHVibGljIERpR3JhcGgoaW50IFYpIHsKCQl0aGlzLm51bVZlcnRpY2VzID0gVjsKCQl0aGlzLmFkakxpc3QgPSBuZXcgSGFzaE1hcDxJbnRlZ2VyLExpc3Q8SW50ZWdlcj4+KFYpOwoJCXRoaXMudmlzdGVkU3RhdHVzID0gbmV3IEhhc2hNYXA8SW50ZWdlciwgQm9vbGVhbj4oVikgOyAKCX0KCgkvKioKCSAqIEVkZ2UgaW4gYSBkaXJlY3RlZCBncmFwaAoJICovCglwcm90ZWN0ZWQgdm9pZCBhZGRFZGdlKGludCBzcmMsIGludCBkZXN0KSB7CgkJTGlzdDxJbnRlZ2VyPiBsaXN0PWFkakxpc3QuZ2V0KHNyYyk7CQkJCgkJaWYobGlzdD09bnVsbCkKCQkJbGlzdD1uZXcgQXJyYXlMaXN0PEludGVnZXI+KCk7CgoJCWxpc3QuYWRkKGRlc3QpOwoJCWFkakxpc3QucHV0KHNyYyxsaXN0KTsJCgkJdmlzdGVkU3RhdHVzLnB1dChzcmMsIGZhbHNlKTsgIC8vdmlzaXQgc3RhdHVzIHNldCB0byBmYWxzZQoJCXZpc3RlZFN0YXR1cy5wdXQoZGVzdCwgZmFsc2UpOwoJfQoKCS8qKgoJICogREZTIHJ1biBvbiBhIGdpdmVuIHZlcnRleAoJICogQHBhcmFtIHZlcnRleAoJICovCglwcm90ZWN0ZWQgdm9pZCBkZnNVdGlsKGludCB2ZXJ0ZXgpewoJCUxpc3QgPEludGVnZXI+IGxpc3QgPSBhZGpMaXN0LmdldCh2ZXJ0ZXgpIDsKCgkJdmlzdGVkU3RhdHVzLnB1dCh2ZXJ0ZXgsIHRydWUpIDsKCQlTeXN0ZW0ub3V0LnByaW50KHZlcnRleCArICJcdCIpOwoJCQoJCWlmKGxpc3QhPW51bGwpewoJCQlpbnQgc2l6ZSA9IGxpc3Quc2l6ZSgpOwoJCQlmb3IoaW50IGkgPSAwO2kgPCBzaXplIDsgaSsrKXsKCQkJCWludCB2PWxpc3QuZ2V0KGkpOwoJCQkJaWYoIXZpc3RlZFN0YXR1cy5nZXQodikpCgkJCQkJZGZzVXRpbCh2KTsKCQkJfQoJCX0KCX0KfQovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovKioKICogU0NDIGZvciBhIGRpcmVjZXRlZCBHcmFwaAogKiBAYXV0aG9yIFByYXRlZWsKICovCiBjbGFzcyBTQ0MgZXh0ZW5kcyBEaUdyYXBoewoKCS8vU3RhY2sgdG8gaG9sZCBmaW5pc2hpbmcgdGltZXMgaS5lIHJldmVyc2UgcG9zdC1vcmRlciBvZiBERlMKCXByaXZhdGUgU3RhY2s8SW50ZWdlcj4gc3RhY2sgPSBuZXcgU3RhY2s8SW50ZWdlcj4oKTsKCQoJLy9BZGphY2VuY3kgTGlzdCB0byBob2xkIHRyYW5zcG9zZSBHcmFwaAoJcHJpdmF0ZSBNYXA8SW50ZWdlcixMaXN0PEludGVnZXI+PiByZXZlcnNlQWRqTGlzdDsKCQoJLyoqQ29udHJ1Y3RvcgoJICogSWYgbnVtYmVyIG9mIHZlcnRpY2VzIGlzIG5vdCBnaXZlbgoJICovCglwdWJsaWMgU0NDKCkgewoJCXRoaXMucmV2ZXJzZUFkakxpc3QgPSBuZXcgSGFzaE1hcDxJbnRlZ2VyLExpc3Q8SW50ZWdlcj4+KG51bVZlcnRpY2VzKSA7IAoJfQoJCgkvKioKCSAqIENvbnN0cnVjdG9yOiBJZiBudW1iZXIgb2YgdmVydGljZXMgaXMgZ2l2ZW4KCSAqLwoJcHVibGljIFNDQyhpbnQgbnVtVmVydGljZXMpIHsKCQlzdXBlcihudW1WZXJ0aWNlcyk7CgkJdGhpcy5yZXZlcnNlQWRqTGlzdCA9IG5ldyBIYXNoTWFwPEludGVnZXIsTGlzdDxJbnRlZ2VyPj4obnVtVmVydGljZXMpIDsgCgl9CgoKCS8qPT09PT09PT09Q29tcHV0ZXMgU0NDIFN0YXJ0cz09PT09PT09PT09PT09PT09PT0qLwoJLyoqCgkgKiBDb21wdXRlcyBTQ0MsIHBlcmZvcm1zIEtvc2FyYWp1J3MgU3RlcHMKCSAqLwoJcHJpdmF0ZSB2b2lkIGNvbXB1dGVTQ0MoU0NDIGcpewoJCQoJCS8vU3RlcDE6IFJldmVyc2UgR3JhcGgKCQkvL1RyYW5zcG9zZSBHcmFwaAoJCXRyYW5zcG9zZShnKTsKCQkKCQlTZXQ8TWFwLkVudHJ5PEludGVnZXIsQm9vbGVhbj4+IHNldD0gdmlzdGVkU3RhdHVzLmVudHJ5U2V0KCk7CgkJSXRlcmF0b3I8TWFwLkVudHJ5PEludGVnZXIsIEJvb2xlYW4+PiBpdD0gc2V0Lml0ZXJhdG9yKCk7CgkJCgkJLy9TdGVwIDIgOiBGaWxsIFN0YWNrCgkJIC8vMXN0IERGUyBvbiBSZXZlcnNlZCBHcmFwaAoJCS8vQ2FsY2F0aW5nIFJldmVyc2UgUG9zdCBvcmRlcgoJCXdoaWxlKGl0Lmhhc05leHQoKSl7CgkJCU1hcC5FbnRyeTxJbnRlZ2VyLCBCb29sZWFuPiBlbnRyeT1pdC5uZXh0KCk7CgkJCWludCB2ZXJ0ZXg9IGVudHJ5LmdldEtleSgpOwoJCQlib29sZWFuIGlzVmlzaXRlZD0gZW50cnkuZ2V0VmFsdWUoKTsKCQkJaWYoIWlzVmlzaXRlZCl7CgkJCQlmaWxsT3JkZXJTdGFja0RGUyh2ZXJ0ZXgpOwoJCQl9CgkJfQoJCQoJCS8vUmVzZXQgVmlzaXQgU3RhdHVzCgkJcmVzZXRWaXNpdFN0YXR1cygpOwoJCQoJCQoJCVN5c3RlbS5vdXQucHJpbnRsbigiU0NDcyBvZiBEaWdyYXBoOiAiKTsKCQkKCQkvL1N0ZXAgMzogUnVuIERGUyB1c2luZyB0aGUgU3RhY2sKCQkvLzJuZCBERlMgb24gT3JpZ2luYWwgR3JhcGgKCQl3aGlsZSghc3RhY2suaXNFbXB0eSgpKXsKCQkKCQkJaW50IHBvcGVkPXN0YWNrLnBvcCgpOwoJCQlpZighdmlzdGVkU3RhdHVzLmdldChwb3BlZCkpCgkJCXsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiPT09PT09PT09PT09PT09PT09PT09PT09PT09Iik7CgkJCQlkZnNVdGlsKHBvcGVkKTsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigpOwoJCQl9CgkJCQoJCX0KCQlTeXN0ZW0ub3V0LnByaW50bG4oIj09PT09PT09PT09PT09PT09PT09PT09PT09PSIpOwoJfQoKCS8qPT09PT09PT09PT09PVJldmVyc2luZyBvZiBHcmFwaCBTdGFydHM9PT09PT09PT09PT09PT09PT0gKi8KCS8qKgoJICogVHJhbnNwb3NlIGdpdmVuIEdyYXBoLCBpZS4gcmV2ZXJzZSBhbGwgdGhlIGVkZ2VzCgkgKiBAcGFyYW0gZwoJICovCglwcml2YXRlIHZvaWQgdHJhbnNwb3NlKFNDQyBnKXsKCgkJU2V0PE1hcC5FbnRyeTxJbnRlZ2VyLCBCb29sZWFuPj4gc2V0PXZpc3RlZFN0YXR1cy5lbnRyeVNldCgpOwkKCQlJdGVyYXRvcjxNYXAuRW50cnk8SW50ZWdlciwgQm9vbGVhbj4+IGl0ZXJhdG9yPXNldC5pdGVyYXRvcigpOwoJCQoJCXdoaWxlKGl0ZXJhdG9yLmhhc05leHQoKSkKCQl7CgkJCU1hcC5FbnRyeTxJbnRlZ2VyLEJvb2xlYW4+IG5vZGU9IGl0ZXJhdG9yLm5leHQoKTsKCQkJaW50IHZlcnRleD1ub2RlLmdldEtleSgpOwoJCQlMaXN0PEludGVnZXI+IGxpc3Q9YWRqTGlzdC5nZXQodmVydGV4KTsKCgkJCWlmKGxpc3QhPW51bGwpCgkJCXsKCQkJCWludCBzaXplPWxpc3Quc2l6ZSgpOwoJCQkJZm9yKGludCBpPTA7aSA8c2l6ZTsgKytpKQoJCQkJewoJCQkJCWludCBhZGpOb2RlPWxpc3QuZ2V0KGkpOwoJCQkJCWcuYWRkUmV2ZXJzZUVkZ2UodmVydGV4LGFkak5vZGUpOwoJCQkJfQoJCQl9CgkJfQoJfQoJCgkvKioKCSAqIEFkZGluZyByZXZlcnNlIGVkZ2UgY29tcGFyZWQgdG8gb3JpZ2luYWwgZ3JhcGgsIAoJICogZWRnZShkZXN0LS0+c3JjKQoJICovCglwcml2YXRlIHZvaWQgYWRkUmV2ZXJzZUVkZ2UoaW50IHNyYywgaW50IGRlc3QpIHsKCQlMaXN0PEludGVnZXI+IGxpc3Q9cmV2ZXJzZUFkakxpc3QuZ2V0KGRlc3QpOwoJCQoJCWlmKGxpc3Q9PW51bGwpCQoJCQlsaXN0PW5ldyBBcnJheUxpc3Q8SW50ZWdlcj4oKTsKCQkKCQlsaXN0LmFkZChzcmMpOwoJCXJldmVyc2VBZGpMaXN0LnB1dChkZXN0LGxpc3QpOwoJfQoKCS8qPT09PT09PT09PT09PVJldmVyc2luZyBvZiBHcmFwaCBFbmRzPT09PT09PT09PT09PT09PT09ICovCgkKCS8qID09PT09PT09PT09PT0gRmlsbGluZyBUaGUgU3RhY2sgU3RhcnRzID09PT09PT09PT09PT09PSovCgkvKioKCSAqIEZpbGwgdGhlIHN0YWNrIHRvIGZvcm0gcmV2ZXJzZSBwb3N0LW9yZGVyIHVzaW5nIERGUwoJICogQHBhcmFtIHZlcnRleAoJICovCglwcml2YXRlIHZvaWQgZmlsbE9yZGVyU3RhY2tERlMoaW50IHZlcnRleCl7CgoJCXZpc3RlZFN0YXR1cy5wdXQodmVydGV4LCB0cnVlKTsKCQlMaXN0PEludGVnZXI+IGxpc3Q9cmV2ZXJzZUFkakxpc3QuZ2V0KHZlcnRleCk7CgoJCWlmKGxpc3QhPW51bGwpewoJCQlpbnQgc2l6ZT1saXN0LnNpemUoKTsKCQkJCgkJCWZvcihpbnQgaT0wO2k8c2l6ZTtpKyspewoJCQkJaW50IGFkak5vZGU9IGxpc3QuZ2V0KGkpOwoJCQkJYm9vbGVhbiBpc1Zpc2l0ZWQgPSB2aXN0ZWRTdGF0dXMuZ2V0KGFkak5vZGUpOwoJCQkJCgkJCQlpZighaXNWaXNpdGVkKQoJCQkJCWZpbGxPcmRlclN0YWNrREZTKGFkak5vZGUpOwoJCQl9CgkJfQoJCXN0YWNrLnB1c2godmVydGV4KTsgLy9QdXNoIHRoZSB2ZXJ0ZXggd2hlbiBhbGwgY29ubmVjdGluZyBsaW5rcyBwcm9jZXNzZWQKCX0KCQoJLyogPT09PT09PT09PT09PSBGaWxsaW5nIFRoZSBTdGFjayBFbmRzID09PT09PT09PT09PT09PSovCgkKCS8qKgoJICogUmVzZXQgVmlzaXQgU3RhdHVzIG9mIGFsbCB2ZXJ0aWNlcwoJICovCglwcml2YXRlIHZvaWQgcmVzZXRWaXNpdFN0YXR1cygpewoJCWZvciAoTWFwLkVudHJ5PEludGVnZXIsIEJvb2xlYW4+IGVudHJ5IDogdmlzdGVkU3RhdHVzLmVudHJ5U2V0KCkpIAoJCSAgICBlbnRyeS5zZXRWYWx1ZShmYWxzZSk7Cgl9CgkKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKCQkvL1Rlc3QgQ2FzZTE6IAoJCS8qaW50IG51bVZlcnRpY2VzID0gNTsKCQlTQ0MgZz1uZXcgU0NDKG51bVZlcnRpY2VzKTsKCQlnLmFkZEVkZ2UoMSwgMCk7CgkJZy5hZGRFZGdlKDAsIDIpOwoJCWcuYWRkRWRnZSgyLCAxKTsKCQlnLmFkZEVkZ2UoMCwgMyk7CgkJZy5hZGRFZGdlKDMsIDQpOwoJCWcuY29tcHV0ZVNDQyhnKTsqLwoJCQoJCS8vVGVzdCBDYXNlMjogCgkJaW50IG51bVZlcnRpY2VzID0gMTE7CgkJU0NDIGc9bmV3IFNDQyhudW1WZXJ0aWNlcyk7CgkJZy5hZGRFZGdlKDEsIDIpOwoJCWcuYWRkRWRnZSgyLCAzKTsKCQlnLmFkZEVkZ2UoMywgMSk7CgkJZy5hZGRFZGdlKDMsIDQpOwoJCWcuYWRkRWRnZSgzLCA3KTsKCQlnLmFkZEVkZ2UoNywgNCk7CgkJZy5hZGRFZGdlKDQsIDYpOwoJCWcuYWRkRWRnZSg2LCA3KTsKCQlnLmFkZEVkZ2UoNCwgNSk7CgkJZy5hZGRFZGdlKDUsIDYpOwoJCWcuYWRkRWRnZSg0LCA5KTsKCQlnLmFkZEVkZ2UoNSwgOCk7CgkJZy5hZGRFZGdlKDgsIDkpOwoJCWcuYWRkRWRnZSg5LCAxMCk7CgkJZy5hZGRFZGdlKDEwLCA4KTsKCQlnLmFkZEVkZ2UoMTEsIDEwKTsKCQlnLmFkZEVkZ2UoMTEsIDkpOwoJCWcuYWRkRWRnZSgyLCAxMSk7CgkJZy5jb21wdXRlU0NDKGcpOwoJCQoJCQoJfQp9Cgo=