Sunday, December 1, 2013

Find Cycles In A Directed Graph (DAG)


In the mathematical theory of directed graphs, a graph is said to be strongly connected if every vertex is reachable from every other vertex. Wikipedia

  • The condensation of G is a directed acyclic graph that has a vertex for every strongly connected component of G and an edge for every two components that are connected by an edge in G. Wikipedia

  • An arbitrary directed graph may also be transformed into a DAG, called its condensation, by contracting each of its strongly connected components into a single supervertex. Wikipedia


    The strongly connected components of a directed graph may be found using an algorithm that uses depth-first search in combination with two stacks, one to keep track of the vertices in the current component and the second to keep track of the current search pathWikipedia


  • One of the best known algorithm to find the strongly connected component is Tarjan's strongly connected components algorithm. Wikipedia

  • The basic algorithm steps are:

  • 1. Start from any arbitrary vertex.

  • 2. DFS from that vertex. For each node x, keep two numbers, dfs_index[x] and dfs_lowval[x].
  • dfs_index[x] stores when that node is visited, while dfs_lowval[x] = min( dfs_low[k]) where
  • k is all the children of x that is not the directly parent of x in the dfs-spanning tree.

  • 3. All nodes with the same dfs_lowval[x] are in the same strongly connected component.



  • 	    public void strongConnect(AdjMatrixDirectGraph<T> graph, Vertex<T> start) {
    	        start.index = index;
    	        start.lowval = index;
    	        index++;
    	        stack.push(start);
    	         
    	        List<Vertex<T>> neighbors = graph.getNeighbors(start);
    	         
    	        for(int i = 0; i < neighbors.size(); i++) {
    	        	Vertex<T> neighbor = neighbors.get(i);
    	             
    	            if(neighbor.index == null) {
    	            	strongConnect(graph, neighbor);
    	            	start.lowval = Math.min(start.lowval, neighbor.lowval);
    	            }
    	            else if(stack.contains(neighbor)) {
    	            	start.lowval = Math.min(start.lowval, neighbor.index);
    	            }
    	        }
    	         
    	        if(start.lowval == start.index) {
    	            List<Vertex<T>> subset = new ArrayList<Vertex<T>>();
    	            Vertex<T> neighbor = null;
    	             
    	            while(start != neighbor) {
    	            	neighbor = stack.pop();
    	            	subset.add(neighbor);
    	            }
    	             
    	            set.add(subset);
    	        }
    	         
    	    }
    	}
    
    







  • From the strongly connected component, we can construct a separate DAG, from which we can find all cycles using modified Hierholzer's algorithm. 

  • The key of the algorithm is to have two stacks, the first one is for storing the forward path and the other is for backtracking. The backtracking is needed to cover unvisited edges for vertexes with multiple unvisited edges. 








  • 		public List<Edge<T>> findCycle(List<Edge<T>> prefix, Vertex<T> start) {
    			Stack<Edge<T>> forward =new Stack<Edge<T>>();
    			Stack<Edge<T>> backtrack =new Stack<Edge<T>>();
    			Edge<T> e = getUnvisitedEdge(start);
    			while (e!=null) {
    				e.visited=true;
    				forward.push(e);
    				e = getUnvisitedEdge(e.end);
    			}
    			
    			while ( ( !forward.isEmpty() ) ) {
    				e = forward.pop();
    				backtrack.push(e);
    			}
    
    			List<Edge<T>> path = new LinkedList<Edge<T>>();
    			if (prefix!=null) {
    				for (Edge<T> e1 : prefix) {
    					path.add(e1);
    				}
    			}
    			while(!backtrack.isEmpty()) {
    				Edge<T> edge = backtrack.pop();
    				path.add(edge);
    			}
    			return path;
    		}
    


    Here is the entire source code with a test case:
    package com.stones333.algorithm.graph;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    import java.util.Stack;
    
    
    /**
     * Find all cycles in DAG
     * 
     * @author stones
     *
     */
    
    public class GraphFindCycles {
    	
    	static private class Vertex<T> {
    		public T label;
    		public boolean visited=false;
    		public Integer index=null;
    		public Integer lowval=null;
    		public Vertex(T n) {
    			this.label=n;
    		}
    		@Override
    		public String toString() {
    			return "Vertex-" + label;
    		}
    
    		@Override
    		public int hashCode() {
    			final int prime = 31;
    			int result = 1;
    			result = prime * result + ((label == null) ? 0 : label.hashCode());
    			result = prime * result + (visited ? 1231 : 1237);
    			return result;
    		}
    		@Override
    		public boolean equals(Object obj) {
    			if (this == obj) return true;
    			if (obj == null) return false;
    			if (getClass() != obj.getClass()) return false;
    			Vertex other = (Vertex) obj;
    			if (label == null) {
    				if (other.label != null) return false;
    			} else if (!label.equals(other.label)) return false;
    			if (visited != other.visited) return false;
    			return true;
    		}
    	}
    
    	static private class Edge<T> {
    		public Vertex<T> start;
    		public Vertex<T> end;
    		public boolean visited=false;
    		public Edge(Vertex<T> start, Vertex<T> end) {
    			this.start=start;
    			this.end=end;
    		}
    		@Override
    		public String toString() {
    			return "Edge [start=" + start + ", end=" + end + ", visited="
    					+ visited + "]";
    		}
    		
    	}
    
    	
    	static private interface GraphInterface<T> {
    		public void addVertex(Vertex<T> n) ;
    		public boolean isVertexExist(Vertex<T> vertex);
    		public void addEdge(Vertex<T> start, Vertex<T> end, double weight) ;
    		public Vertex<T> getUnvisitedChildren(Vertex<T> n);
    		
    	}
    
    	static private abstract class Graph<T> implements GraphInterface<T> {
    		
    		//DFS traversal of a tree is performed by the dfs() function
    		public void dfs(Vertex<T> start) {
    			//DFS uses Stack data structure
    			Stack<Vertex<T>> stack =new Stack<Vertex<T>>();
    			start.visited=true;
    			stack.push(start);
    			printNode(start);
    			while(!stack.isEmpty()) {
    				Vertex<T> n= stack.peek();
    				Vertex<T> child=getUnvisitedChildren(n);
    				if(child!=null) {
    					child.visited=true;
    					stack.push(child);
    					printNode(child);
    				} else {
    					stack.pop();
    				}
    			}
    		}
    
    		//BFS traversal of a graph is performed by the bfs() function
    		public void bfs(Vertex<T> start)
    		{
    			//BFS uses Queue data structure
    			Queue<Vertex<T>> que=new LinkedList<Vertex<T>>();
    			start.visited=true;
    			que.add(start);
    			printNode(start);
    			
    			while(!que.isEmpty()) {
    				Vertex<T> n=(Vertex<T>)que.remove();
    				Vertex<T> child=null;
    				while((child=getUnvisitedChildren(n))!=null) {
    					child.visited=true;
    					que.add(child);
    					printNode(child);
    				}
    			}
    		}
    
    
    		public void printNode(Vertex<T> n) {
    			System.out.print(n.label+" ");
    		}
    	}
    
    	static public class DirectedGraphFindAllPath<T>  {
    		List<Edge<T>> edges=new ArrayList<Edge<T>>();
    		List<Vertex<T>> vetexes=new ArrayList<Vertex<T>>();
    
    		
    		public DirectedGraphFindAllPath (StronglyConnectedTarjan<T> scc, Vertex<T> start) {
    			List<WeightedEdge<T>> edges = scc.findStrongConnectEdges (start);
    			for (WeightedEdge<T> edge : edges ) {
    				this.addEdge(edge.start, edge.end);
    			}
    		}
    		
    		public DirectedGraphFindAllPath<T> addVetex(Vertex<T> n) {
    			vetexes.add(n);
    			return this;
    		}
    
    		public boolean isVetexExist(Vertex<T> vetex) {
    			return ( vetexes.indexOf(vetex) >=0 ) ;
    		}
    
    		public boolean isAllEdgeVisited() {
    			for (Edge<T> e : edges) {
    				if (! e.visited) return false;
    			}
    			return true;
    		}
    
    
    		public List<List<Edge<T>>> findCycles(Vertex<T> start) {
    			List<List<Edge<T>>> pathes = new LinkedList<List<Edge<T>>>();
    			
    			List<Edge<T>> cycle = findCycle(null, start);
    			pathes.add(cycle);
    			
    			List<Edge<T>> current = new LinkedList<Edge<T>>();
    			for (Edge<T> edge : cycle ) {
    				current.add(edge);
    				if ( hasUnvisitedEdge (edge.end) ) {
    					List<Edge<T>> p = findCycle(current, edge.end);
    					pathes.add(p);
    				}
    			}
    			return pathes;
    		}
    
    		
    		/**
    		 * The key of the algorithm is to have two stacks, 
    		 * the first one is for storing the forward path and the other is for backtracking. 
    		 * The backtracking is needed to cover unvisited edges for vertexes with multiple edges. 
    		 * 
    		 * @param prefix
    		 * @param start
    		 * @return
    		 */
    		public List<Edge<T>> findCycle(List<Edge<T>> prefix, Vertex<T> start) {
    			Stack<Edge<T>> forward =new Stack<Edge<T>>();
    			Stack<Edge<T>> backtrack =new Stack<Edge<T>>();
    			Edge<T> e = getUnvisitedEdge(start);
    			while (e!=null) {
    				e.visited=true;
    				forward.push(e);
    				e = getUnvisitedEdge(e.end);
    			}
    			
    			while ( ( !forward.isEmpty() ) ) {
    				e = forward.pop();
    				backtrack.push(e);
    			}
    
    			List<Edge<T>> path = new LinkedList<Edge<T>>();
    			if (prefix!=null) {
    				for (Edge<T> e1 : prefix) {
    					path.add(e1);
    				}
    			}
    			while(!backtrack.isEmpty()) {
    				Edge<T> edge = backtrack.pop();
    				path.add(edge);
    			}
    			return path;
    		}
    		
    		/**
    		 * 1. Choose any starting vertex v, and follow a trail of edges from that vertex until returning to v. 
    		 * It is not possible to get stuck at any vertex other than v, because the even degree of all vertices ensures that, 
    		 * when the trail enters another vertex w there must be an unused edge leaving w. 
    		 * The tour formed in this way is a closed tour, but may not cover all the vertices and edges of the initial graph.
    		 * 
    		 * 2. As long as there exists a vertex v that belongs to the current tour but that has adjacent edges not part of the tour, 
    		 * start another trail from v, following unused edges until returning to v, 
    		 * and join the tour formed in this way to the previous tour. 
    		 * 
    		 * @param start
    		 * @return
    		 */
    		public List<Edge<T>> findHierholzerPath(Vertex<T> start) {
    			Stack<Edge<T>> forward =new Stack<Edge<T>>();
    			Stack<Edge<T>> backtrack =new Stack<Edge<T>>();
    			Edge<T> e = getUnvisitedEdge(start);
    			while (e!=null) {
    				e.visited=true;
    				forward.push(e);
    				e = getUnvisitedEdge(e.end);
    			}
    			
    			while ( ( !forward.isEmpty() ) ) {
    				e = forward.pop();
    				backtrack.push(e);
    				e = getUnvisitedEdge(e.start);
    				while (e!=null) {
    					e.visited = true;
    					forward.push(e);
    					e = getUnvisitedEdge(e.end);
    				}
    			}
    
    			List<Edge<T>> path = new LinkedList<Edge<T>>();
    			while(!backtrack.isEmpty()) {
    				Edge<T> edge = backtrack.pop();
    				path.add(edge);
    			}
    
    			return path;
    		}
    
    		public void printPath(List<Edge<T>> path) {
    			for (int i=0; i<path.size(); i++) {
    				System.out.print(path.get(i).start.label + "->" + path.get(i).end.label + " ");
    			}
    		}
    
    		public List<Edge<T>> findHierholzerPath(Vertex<T> start, Vertex<T> end) {
    
    			List<Edge<T>> path = findHierholzerPath(start);
    			if (path==null || path.size()==0) {
    				System.out.println ("No Eulerian path found!");
    			} else {
    				if ( path.get(path.size()-1).end == end ) {
    					System.out.println ("Eulerian path found:");
    					this.printPath(path);		
    				} else {
    					System.out.println ("No Eulerian path found!");
    				}
    			}
    			return path;
    		}
    
    
    		//This method will be called to make connect two nodes
    		public DirectedGraphFindAllPath<T> addEdge(Vertex<T> start, Vertex<T> end, int weight ) {
    			if ( ! isVetexExist(start) ) addVetex(start);
    			if ( ! isVetexExist(end) ) addVetex(end);
    			
    			Edge<T> edge = new Edge<T>(start, end);
    			edges.add(edge);
    			return this;
    		}
    
    		
    		//This method will be called to make connect two nodes
    		public DirectedGraphFindAllPath<T> addEdge(Vertex<T> start, Vertex<T> end) {
    			if ( ! isVetexExist(start) ) addVetex(start);
    			if ( ! isVetexExist(end) ) addVetex(end);
    			
    			Edge<T> edge = new Edge<T>(start, end);
    			edges.add(edge);
    			return this;
    		}
    		
    		public Vertex<T> getUnvisitedChildren(Vertex<T> n) {
    			for (Edge<T> e : edges) {
    				if ( e.visited==false && e.start.equals(n) ) {
    					e.visited=true;
    					return e.end;
    				}
    			}
    			return null;
    		}
    
    		public boolean hasUnvisitedEdge(Vertex<T> n) {
    			for (Edge<T> e : edges) {
    				if ( e.visited==false && e.start.equals(n) ) {
    					return true;
    				}
    			}
    			return false;
    		}
    
    		
    		public Edge<T> getUnvisitedEdge(Vertex<T> n) {
    			for (Edge<T> e : edges) {
    				if ( e.visited==false && e.start.equals(n) ) {
    					e.visited=true;
    					return e;
    				}
    			}
    			return null;
    		}
    
    		
    		public void clearNodes() {
    			for ( Edge<T> e : edges)
    				e.visited=false;
    			
    			for ( Vertex<T> v : vetexes)
    				v.visited=false;
    
    		}
    	}
    
    	static private class AdjMatrixDirectGraph<T> extends Graph<T> implements GraphInterface<T> {
    		public ArrayList<Vertex<T>> vertexes=new ArrayList<Vertex<T>>();
    		public double[][] adjMatrix;
    
    		
    		public void addVertex(Vertex<T> n) {
    			vertexes.add(n);
    		}
    
    		public boolean isVertexExist(Vertex<T> vertex) {
    			return ( vertexes.indexOf(vertex) >=0 ) ;
    		}
    		
    		public List<Vertex<T>> getVertexes () {
    			return vertexes;
    		}
    
    		public void addEdge(Vertex<T> start, Vertex<T> end) {
    			addEdge(start, end, 1);
    		}
    
    		
    		//This method will be called to make connect two nodes
    		public void addEdge(Vertex<T> start, Vertex<T> end, double weight) {
    			if ( ! isVertexExist(start) ) addVertex(start);
    			if ( ! isVertexExist(end) ) addVertex(end); 
    
    			if ( initAdjMatrix() ) {
    				int startIndex=vertexes.indexOf(start);
    				int endIndex=vertexes.indexOf(end);
    				if (startIndex>=0 && endIndex>=0) {
    					adjMatrix[startIndex][endIndex]=weight;
    				}
    			}
    		}
    
    		public boolean initAdjMatrix() {
    			if (vertexes.size()<=0) return false;
    			adjMatrix=buildAdjMatrix(adjMatrix, vertexes.size());
    			return true;
    		}
    
    		private double [][] buildAdjMatrix(double[][] prevMatrix, int newSize) {
    			if (newSize==0) return null;
    			double[][] matrix=new double[newSize][newSize];
    			
    			for (int i=0; i<newSize; i++) 
    				for (int j=0; j<newSize; j++) 
    					matrix[i][j] = Double.POSITIVE_INFINITY;
    
    			if (prevMatrix!=null) {
    				for (int i=0; i<prevMatrix.length; i++) 
    					for (int j=0; j<prevMatrix[i].length; j++) 
    						matrix[i][j] = prevMatrix[i][j];
    			}
    			return matrix;
    		}
    		
    		
    		public List<Vertex<T>> getNeighbors(Vertex<T> n) {
    			List<Vertex<T>> list = new ArrayList <Vertex<T>>();
    			int index=vertexes.indexOf(n);
    			for (int j=0; j<vertexes.size(); j++) {
    				if( adjMatrix[index][j]!=Double.POSITIVE_INFINITY ) {
    					list.add((Vertex<T>)vertexes.get(j));
    				}
    			}
    			return list;
    		}
    		
    		public Vertex<T> getUnvisitedChildren(Vertex<T> n) {
    			
    			int index=vertexes.indexOf(n);
    			int j=0;
    			while(j<vertexes.size()) {
    				if( adjMatrix[index][j]!=Double.POSITIVE_INFINITY && vertexes.get(j).visited==false ) {
    					return (Vertex<T>)vertexes.get(j);
    				}
    				j++;
    			}
    			return null;
    		}
    
    		public List<WeightedEdge<T>> getEdges(Vertex<T> n) {
    			
    			List<WeightedEdge<T>> edges = new LinkedList<WeightedEdge<T>>();
    			int index=vertexes.indexOf(n);
    			int j=0;
    			while(j<vertexes.size()) {
    				if( adjMatrix[index][j]!=Double.POSITIVE_INFINITY  ) {
    					edges.add(new WeightedEdge<T> (n, vertexes.get(j),  adjMatrix[index][j]) );
    				}
    				j++;
    			}
    			return edges;
    		}
    
    		public List<WeightedEdge<T>> getEdges() {
    			List<WeightedEdge<T>> edges = new LinkedList<WeightedEdge<T>>();
    			for (int i=0; i<adjMatrix.length; i++) {
    				for (int j=0; j<adjMatrix[i].length; j++) {
    					if( adjMatrix[i][j]!=Double.POSITIVE_INFINITY  ) {
    						edges.add(new WeightedEdge<T> (vertexes.get(i), vertexes.get(j),  adjMatrix[i][j]) );
    					}
    				}
    			}
    			return edges;
    		}
    
    
    		public void printVertexes() {
    			for (int i=0; i<vertexes.size(); i++ ) {
    				System.out.print(vertexes.get(i) + " " );
    			}
    			System.out.println();
    		}
    
    		
    		
    		//Utility methods for clearing visited property of node
    		public void clearNodes() {
    			int i=0;
    			while(i<vertexes.size()) {
    				vertexes.get(i).visited=false;
    				i++;
    			}
    		}
    		
    	}
    
    	static private class WeightedEdge<T>  extends  Edge<T> {
    		public final double weight;
    		public boolean visited=false;
    		public WeightedEdge(Vertex<T> start, Vertex<T> end, double weight) {
    			super(start, end);
    			this.weight=weight;
    		}
    		
    
    		public int compareTo(WeightedEdge<T> that) {
    			if (this.weight < that.weight) 
    				return -1;
    			else if (this.weight > that.weight) 
    				return +1;
    			else 
    				return 0;
    		 }
    
    		@Override
    		public String toString() {
    			return "WeightedEdge [start=" + start + ", end=" + end
    					+ ", weight=" + weight + ", visited=" + visited + "]";
    		}
    	}
    
    	
    	static public class StronglyConnectedTarjan<T> {
    		public AdjMatrixDirectGraph<T> graph;
    		public int index;
    	    public Stack<Vertex<T>> stack;
    	    public List<List<Vertex<T>>> set;
    
    	    public void printConnected () {
    	    	  for(int i = 0; i < set.size(); i++) {
    	              System.out.println("Set " + i + ": " + Arrays.toString(set.get(i).toArray()));
    	    	  }
    	    }
    
    	    public StronglyConnectedTarjan(AdjMatrixDirectGraph<T> graph) {
    	    	this.graph = graph;
    	    	stack = new Stack<Vertex<T>> ();
    	    	set = new ArrayList<List<Vertex<T>>> ();
    	    	
    	    	for( Vertex<T> node : graph.vertexes) {
    	            if(node.index == null) 
    	            	strongConnect(graph, node);
    	        }
    	    }
    	    
    	    public List<WeightedEdge<T>> findStrongConnectEdges (Vertex<T> node) {
    	    	List<WeightedEdge<T>> edges = new ArrayList<WeightedEdge<T>>();
    	    	 for (List<Vertex<T>> c : set) {
    	    		 if ( c.contains(node) ) {
    	    			 for (int i=0; i<graph.adjMatrix.length; i++) {
    	    				 for (int j=0; j<graph.adjMatrix[i].length; j++) {
    	    					
    	    						if( graph.adjMatrix[i][j]!=Double.POSITIVE_INFINITY 
    	    								&& c.contains(graph.vertexes.get(i)) 
    	    								&& c.contains(graph.vertexes.get(j)) ) {
    	    							edges.add(new WeightedEdge<T> (graph.vertexes.get(i), graph.vertexes.get(j),  graph.adjMatrix[i][j]) );
    	    						}
    
    	    				 }
    	    			 }
    	    		 }
    	    	 }
    	    	
    	    	
    	    	return edges;
    	    }
    	    
    
    	    /**
    	     *
    	     * 1. Start from any arbitrary vertex.
    	     * 
    	     * 2. DFS from that vertex. For each node x, keep two numbers, dfs_index[x] and dfs_lowval[x]. 
    	     * dfs_index[x] stores when that node is visited, while dfs_lowval[x] = min( dfs_low[k]) where 
    	     * k is all the children of x that is not the directly parent of x in the dfs-spanning tree.
    	     * 
    	     * 3. All nodes with the same dfs_lowval[x] are in the same strongly connected component.
    	     * 
    	     * @param graph
    	     * @param start
    	     */
    	    public void strongConnect(AdjMatrixDirectGraph<T> graph, Vertex<T> start) {
    	        start.index = index;
    	        start.lowval = index;
    	        index++;
    	        stack.push(start);
    	         
    	        List<Vertex<T>> neighbors = graph.getNeighbors(start);
    	         
    	        for(int i = 0; i < neighbors.size(); i++) {
    	        	Vertex<T> neighbor = neighbors.get(i);
    	             
    	            if(neighbor.index == null) {
    	            	strongConnect(graph, neighbor);
    	            	start.lowval = Math.min(start.lowval, neighbor.lowval);
    	            }
    	            else if(stack.contains(neighbor)) {
    	            	start.lowval = Math.min(start.lowval, neighbor.index);
    	            }
    	        }
    	         
    	        if(start.lowval == start.index) {
    	            List<Vertex<T>> subset = new ArrayList<Vertex<T>>();
    	            Vertex<T> neighbor = null;
    	             
    	            while(start != neighbor) {
    	            	neighbor = stack.pop();
    	            	subset.add(neighbor);
    	            }
    	             
    	            set.add(subset);
    	        }
    	         
    	    }
    	}
    
    	public static void main(String[] args) {
    		System.out.println("testFindCycle -->");
    		testFindCycle();
    
    	}
    
    	private static void testFindCycle() {
    		Vertex<String> nA = new Vertex<String>("A");
    		Vertex<String> nB = new Vertex<String>("B");
    		Vertex<String> nC = new Vertex<String>("C");
    		Vertex<String> nD = new Vertex<String>("D");
    		Vertex<String> nE = new Vertex<String>("E");
    		Vertex<String> nF = new Vertex<String>("F");
    		Vertex<String> nG = new Vertex<String>("G");
    		Vertex<String> nH = new Vertex<String>("H");
    
    		//Create the graph, add nodes, create edges between nodes
    		AdjMatrixDirectGraph<String> g=new AdjMatrixDirectGraph<String>();
    		
    		g.addEdge(nA, nB); g.addEdge(nB, nC); g.addEdge(nC, nA); g.addEdge(nB, nA); 
    		g.addEdge(nD, nB); g.addEdge(nD, nC); g.addEdge(nD, nF);
    		g.addEdge(nF, nD); g.addEdge(nE, nC);
    		g.addEdge(nE, nG); g.addEdge(nG, nE);
    		g.addEdge(nH, nF); g.addEdge(nH, nH);
    
    		StronglyConnectedTarjan<String> scc = new StronglyConnectedTarjan<String>(g);
    //		scc.printConnected();
    //	    List<WeightedEdge<String>> edges = scc.findStrongConnectEdges (nA);
    //	    for (WeightedEdge<String> e: edges) {
    //	    	System.out.println(e);
    //	    }
    	    
    	    DirectedGraphFindAllPath<String> findCycle = new DirectedGraphFindAllPath<String> (scc, nA);
    		List<List<Edge<String>>> pathes = findCycle.findCycles(nA);
    		for (List<Edge<String>> path : pathes) {
    			System.out.println("");
    			System.out.print("cycle: ");
    			findCycle.printPath(path);
    		}
    
    		
    	}
    
    
    }
    
    
    
    


    The graph edges are
    (nA, nB), (nB, nC), (nC, nA), addEdge(nB, nA); (nD, nB), (nD, nC), (nD, nF); (nF, nD), (nE, nC), (nE, nG); (nG, nE), (nH, nF), (nH, nH);

    The output:
    cycle: A->B B->A 
    cycle: A->B B->C C->A 
    

    Enjoy the journey, have fun.

    91 comments:

    1. Hi this sample method

      private static void testFindCycle2() {
      Vertex n1 = new Vertex("1");
      Vertex n2 = new Vertex("2");
      Vertex n4 = new Vertex("4");
      Vertex n5 = new Vertex("5");
      Vertex n13 = new Vertex("13");

      //Create the graph, add nodes, create edges between nodes
      AdjMatrixDirectGraph g=new AdjMatrixDirectGraph();

      g.addEdge(n1, n4);
      g.addEdge(n4, n2);
      g.addEdge(n2, n5);
      g.addEdge(n5, n1);
      g.addEdge(n1, n13);
      g.addEdge(n13, n5);

      StronglyConnectedTarjan scc = new StronglyConnectedTarjan(g);
      // scc.printConnected();
      // List> edges = scc.findStrongConnectEdges (nA);
      // for (WeightedEdge e: edges) {
      // System.out.println(e);
      // }

      DirectedGraphFindAllPath findCycle = new DirectedGraphFindAllPath (scc, n1);
      List>> pathes = findCycle.findCycles(n1);
      for (List> path : pathes) {
      System.out.println("");
      System.out.print("cycle: ");
      findCycle.printPath(path);
      }

      provides this output
      cycle: 1->4 4->2 2->5 5->1 1->13 13->5


      It is not clear if this a bug or not ...
      I think on given example there should be two cycles
      cycle1: 1->4 4->2 2->5 5->1
      cycle2: 1->13 13->5 5->1

      ReplyDelete
    2. Hi, I unable to run the program. Can u pls tell how to do it.
      I did this but I am getting error:
      $javac GraphFindCycles.java
      no error after compile
      $ java GraphFindCycles
      Error: Could not find or load main class GraphFindCycles

      ReplyDelete
    3. Very nice post here and thanks for it .I always like and such a super contents of these post.Excellent and very cool idea and great content of different kinds of the valuable information's.
      rpa training in bangalore
      best rpa training in bangalore
      rpa training in pune | rpa course in bangalore
      rpa training in chennai

      ReplyDelete
    4. I ReGreat For Your Information The Information U have Shared Is Fabulous And Interesting So Please keep Updating Us The Information Shared Is Very Valuable Time Just Went On Reading The Article Python Online Course AWS Online Course Data Science Online Course Hadoop Online Course

      ReplyDelete
    5. An amazing web journal I visit this blog, it's unbelievably wonderful. Oddly, in this blog's content made without a doubt and reasonable. The substance of data is informative.
      Oracle Fusion Financials Online Training
      Oracle Fusion HCM Online Training
      Oracle Fusion SCM Online Training

      ReplyDelete
    6. smart outsourcing solutions is the best outsourcing training
      in Dhaka, if you start outsourcing please
      visit us: graphic design training
      digital marketing training

      ReplyDelete
    7. Visit for Python training in Bangalore:- Python training in bangalore

      ReplyDelete
    8. I am Here to Get Learn Good Stuff About pytho Training, Thanks For Sharing pythonTraining.python training in bangalore

      ReplyDelete
    9. Its help me to improve my knowledge and skills also.im really satisfied in this microsoft azure session.microsoft azure training in bangalore

      ReplyDelete
    10. Being new to the blogging world I feel like there is still so much to learn. Your tips helped to clarify a few things for me as well as giving.python training in bangalore

      ReplyDelete
    11. Thanks for the useful and informative post...very useful...

      aws training

      ReplyDelete
    12. More impressive blog!!! Thanks for shared with us.... waiting for you upcoming data.
      Devops Training in Pune

      ReplyDelete
    13. This comment has been removed by the author.

      ReplyDelete
    14. Whatever we gathered information from the blogs, we should implement that in practically then only we can understand that exact thing clearly, data science online training but it’s no need to do it, because you have explained the concepts very well. It was crystal clear, keep sharing..
      data science tutorial for beginners

      ReplyDelete
    15. Appreciation for sincerely being thoughtful and also for selecting certain mind-blowing courses most of the people really need to be aware of.

      click here formore info.

      ReplyDelete
    16. You are so awesome! I don't think I have read a single thing like this before. So good to discover another person with original thoughts on this subject matter. Seriously.. thanks for starting this up. This website is one thing that is required on the internet, someone with a bit of originality!
      Click here to get More information.

      ReplyDelete
    17. Thannks for sharing the best sites

      Shopclues lucky draw 2020| Shopclues winner 2020|Get to Know Shopclues Lucky Draw Winner 2020. Call Shopclues Helpline Phone Number+91-9835565523 for Shopclues Online Shopping Lucky Draw.
      Shopclues online lucky draw winner
      Shopclues winner 2020
      shopclues car lucky draw

      ReplyDelete
    18. Snapdeal winner 2020 | Dear customer, you can complain here If you get to call and SMS regarding Snapdeal lucky draw, Mahindra xuv 500, lucky draw contest, contact us at to know the actual Snapdeal prize winners 2020.
      Snapdeal winner 2020
      Snapdeal lucky draw winner 2020
      Snapdeal lucky draw contest 2020
      snapdeal winner prizes 2020

      ReplyDelete
    19. This post is really nice and informative. The explanation given is really comprehensive and useful.

      big data hadoop training

      ReplyDelete
    20. This Big data web site definitely has all the information I wanted about this subject and didn’t know who to ask.

      ReplyDelete
    21. Thank you for your detailed analysis.
      And i have a question in findCycle() function:
      1. the backtrack stack stored the reversed elements in the forward stack,
      and then add these elements to path. Acturally, the backtrack stack did nothing, isn't ?

      ReplyDelete
    22. Hi, your article was of great help. I loved the way you shared the information, thanks.
      Amazing article, I highly appreciate your efforts, it was highly helpful. Thank you CEH Training ,CEH Certification, CEH Online Course, Ethicalhacking

      ReplyDelete

    23. Thanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information. 
      Digital Marketing Certification Training
      AWS Certification Training
      Python Certification Training

      ReplyDelete
    24. After going over a handful of the blog articles on your website, I truly appreciate your technique of writing a blog. I bookmarked it to my bookmark technology webpage list and will be checking back in the near future. Please check out my website as well and let me know what you think.

      ReplyDelete
    25. Nice post. Thank you to provide us this useful information. Van Helsing Coat

      ReplyDelete
    26. I read this article. I think You put a lot of effort to create this article. I appreciate your work.

      Rocky Tiger Jacket

      ReplyDelete
    27. Our the purpose is to share the reviews about the latest Jackets,Coats and Vests also share the related Movies,Gaming, Casual,Faux Leather and Leather materials available Suicide Squad Kill The Justice League Harley Quinn Jacket

      ReplyDelete
    28. Amazon Web Service (AWS) is the top rank compared to other cloud services providers like IBM, Microsoft, Google, HP, etc. Best Software Training Institute for AWS Online Training, Provides AWS Online Training Course,

      ReplyDelete
    29. It is perfect time to make some plans for the future and it is time to be happy. I've read this post and if I could I desire to suggest you some interesting things or suggestions. Perhaps you could write next articles referring to this article. I want to read more things about it!
      best data science courses in hyderabad

      ReplyDelete
    30. You completed a number of nice points there. I did a search on the issue and found ExcelR Data Analytics Courses nearly all people will have the same opinion with your blog.

      ReplyDelete
    31. Thank You for sharing good website. bsc 3rd year time table I also recommend to Big Surmise as Tour and Travel directory submission.

      ReplyDelete
    32. Very Informative and useful... Keep it up the great work. I really appreciate your post.
      Primavera Course in Chennai | primavera online training

      ReplyDelete
    33. Thanks for sharing the inforamation about Graph ,visit us for Python Courses Fees

      ReplyDelete
    34. Really wonderful blog completely enjoyed reading and learning to gain the vast knowledge.
      wonderful

      ReplyDelete
    35. Very interesting to read this article. I would like to thank you for the efforts you had made for writing this awesome article. This article inspired me to read more. Keep it up.
      AWS Training in Hyderabad
      AWS Course in Hyderabad

      ReplyDelete
    36. I recently realized that you're already following my social media pages! I thought I'd check out your blog and spend some time reading what you have had to say.
      Data Science Training in Hyderabad
      Data Science Course in Hyderabad

      ReplyDelete
    37. E shram Card is a labor registration portal created by the Labor Department, Government of india.

      ReplyDelete
    38. Computer Full Form is very usefull in students for study in education

      ReplyDelete
    39. K.G.F: Chapter 2 : Directed by Prashanth Neel. With Yash, Sanjay Dutt, Raveena Tandon, Prakash Raj. The blood-soaked land of Kolar Gold Fields

      ReplyDelete
    40. Nice post. Thank you to provide us this useful information. Ranboo Varsity Jacket

      ReplyDelete
    41. jan adhar card very usefull in rajsthan govt. All Process in Download See Now

      ReplyDelete
    42. thanks for sharing amazing information keep posting!
      Oreo TV

      ReplyDelete
    43. Your content is nothing short of brilliant in many ways. I think this is engaging and eye-opening material. Thank you so much for caring about your content and your readers.
      data analytics courses in hyderabad

      ReplyDelete
    44. i like your post and all your headings are good....hindi skill

      ReplyDelete
    45. Love to read it, Waiting For More new Update and I Already Read your Recent Post its Great Thanks.

      Madurai Kamaraj University Time Table 2022
      Shekhawati University Time Table 2022

      ReplyDelete
    46. I found lots of interesting information here.Great work. i like this blog. India No.1 Media

      ReplyDelete
    47. This is a very nice blog and learned more shop here
      knowledge to read this post thanks for sharing this informative post

      ReplyDelete
    48. Unified communications and Ip Pbx includes the connection of various communication systems both for the collaboration tools as the digital workforce.

      ReplyDelete