private int[] rank; // rank[v] = order where vertex v appers in order /// <summary> /// Determines whether the digraph <c>G</c> has a topological order and, if so, /// finds such a topological order. /// </summary> /// <param name="G">the digraph</param> /// public TopologicalX(Digraph G) { // indegrees of remaining vertices int[] indegree = new int[G.V]; for (int v = 0; v < G.V; v++) { indegree[v] = G.Indegree(v); } // initialize rank = new int[G.V]; order = new LinkedQueue <int>(); int count = 0; // initialize queue to contain all vertices with indegree = 0 LinkedQueue <int> queue = new LinkedQueue <int>(); for (int v = 0; v < G.V; v++) { if (indegree[v] == 0) { queue.Enqueue(v); } } for (int j = 0; !queue.IsEmpty; j++) { int v = queue.Dequeue(); order.Enqueue(v); rank[v] = count++; foreach (int w in G.Adj(v)) { indegree[w]--; if (indegree[w] == 0) { queue.Enqueue(w); } } } // there is a directed cycle in subgraph of vertices with indegree >= 1. if (count != G.V) { order = null; } Debug.Assert(check(G)); }
public static void MainTest(string[] args) { int V = int.Parse(args[0]); int E = int.Parse(args[1]); // Eulerian cycle Digraph G1 = DigraphGenerator.EulerianCycle(V, E); DirectedEulerianPath.UnitTest(G1, "Eulerian cycle"); // Eulerian path Digraph G2 = DigraphGenerator.EulerianPath(V, E); DirectedEulerianPath.UnitTest(G2, "Eulerian path"); // add one random edge Digraph G3 = new Digraph(G2); G3.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V)); DirectedEulerianPath.UnitTest(G3, "one random edge added to Eulerian path"); // self loop Digraph G4 = new Digraph(V); int v4 = StdRandom.Uniform(V); G4.AddEdge(v4, v4); DirectedEulerianPath.UnitTest(G4, "single self loop"); // single edge Digraph G5 = new Digraph(V); G5.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V)); DirectedEulerianPath.UnitTest(G5, "single edge"); // empty digraph Digraph G6 = new Digraph(V); DirectedEulerianPath.UnitTest(G6, "empty digraph"); // random digraph Digraph G7 = DigraphGenerator.Simple(V, E); DirectedEulerianPath.UnitTest(G7, "simple digraph"); // 4-vertex digraph //Digraph G8 = new Digraph(new TextInput("eulerianD.txt")); //DirectedEulerianPath.UnitTest(G8, "4-vertex Eulerian digraph"); }
/************************************************************************** * * The code below is solely for testing correctness of the data type. * **************************************************************************/ // Determines whether a digraph has an Eulerian path using necessary // and sufficient conditions (without computing the path itself): // - indegree(v) = outdegree(v) for every vertex, // except one vertex v may have outdegree(v) = indegree(v) + 1 // (and one vertex v may have indegree(v) = outdegree(v) + 1) // - the graph is connected, when viewed as an undirected graph // (ignoring isolated vertices) // This method is solely for unit testing. private static bool hasEulerianPath(Digraph G) { if (G.E == 0) { return(true); } // Condition 1: indegree(v) == outdegree(v) for every vertex, // except one vertex may have outdegree(v) = indegree(v) + 1 int deficit = 0; for (int v = 0; v < G.V; v++) { if (G.Outdegree(v) > G.Indegree(v)) { deficit += (G.Outdegree(v) - G.Indegree(v)); } } if (deficit > 1) { return(false); } // Condition 2: graph is connected, ignoring isolated vertices Graph H = new Graph(G.V); for (int v = 0; v < G.V; v++) { foreach (int w in G.Adj(v)) { H.AddEdge(v, w); } } // check that all non-isolated vertices are connected int s = nonIsolatedVertex(G); BreadthFirstPaths bfs = new BreadthFirstPaths(H, s); for (int v = 0; v < G.V; v++) { if (H.Degree(v) > 0 && !bfs.HasPathTo(v)) { return(false); } } return(true); }
public static void MainTest(string[] args) { TextInput input = new TextInput(args[0]); Digraph G = new Digraph(input); int s = int.Parse(args[1]); NonrecursiveDirectedDFS dfs = new NonrecursiveDirectedDFS(G, s); for (int v = 0; v < G.V; v++) { if (dfs.Marked(v)) { Console.Write(v + " "); } } Console.WriteLine(); }
/// <summary> /// Returns a path digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the path</param> /// <returns>a digraph that is a directed path on <c>V</c> vertices</returns> /// public static Digraph Path(int V) { Digraph G = new Digraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (int i = 0; i < V - 1; i++) { G.AddEdge(vertices[i], vertices[i + 1]); } return(G); }
/// <summary> /// Returns a complete binary tree digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the binary tree</param> /// <returns>a digraph that is a complete binary tree on <c>V</c> vertices</returns> /// public static Digraph BinaryTree(int V) { Digraph G = new Digraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (int i = 1; i < V; i++) { G.AddEdge(vertices[i], vertices[(i - 1) / 2]); } return(G); }
private int[] rank; // rank[v] = position of vertex v in topological order /// <summary> /// Determines whether the digraph <c>G</c> has a topological order and, if so, /// finds such a topological order.</summary> /// <param name="G">the digraph</param> /// public Topological(Digraph G) { DirectedCycle finder = new DirectedCycle(G); if (!finder.HasCycle) { DepthFirstOrder dfs = new DepthFirstOrder(G); order = dfs.ReversePost(); rank = new int[G.V]; int i = 0; foreach (int v in order) { rank[v] = i++; } } }
// does the id[] array contain the strongly connected components? private bool check(Digraph G) { TransitiveClosure tc = new TransitiveClosure(G); for (int v = 0; v < G.V; v++) { for (int w = 0; w < G.V; w++) { if (StronglyConnected(v, w) != (tc.Reachable(v, w) && tc.Reachable(w, v))) { return(false); } } } return(true); }
/// <summary>Computes the strong components of the digraph <c>G</c>.</summary> /// <param name="G">the digraph</param> /// public TarjanSCC(Digraph G) { marked = new bool[G.V]; stack = new LinkedStack <int>(); id = new int[G.V]; low = new int[G.V]; for (int v = 0; v < G.V; v++) { if (!marked[v]) { dfs(G, v); } } // check that id[] gives strong components Debug.Assert(check(G)); }
/// <summary> /// Returns a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges. /// A rooted out-tree is a DAG in which every vertex is reachable from a /// single vertex. /// The DAG returned is not chosen uniformly at random among all such DAGs.</summary> /// <param name="V">the number of vertices</param> /// <param name="E">the number of edges</param> /// <returns>a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges</returns> /// public static Digraph RootedOutDAG(int V, int E) { if (E > (long)V * (V - 1) / 2) { throw new ArgumentException("Too many edges"); } if (E < V - 1) { throw new ArgumentException("Too few edges"); } Digraph G = new Digraph(V); SET <Edge> set = new SET <Edge>(); // fix a topological order int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); // one edge pointing from each vertex, other than the root = vertices[V-1] for (int v = 0; v < V - 1; v++) { int w = StdRandom.Uniform(v + 1, V); Edge e = new Edge(w, v); set.Add(e); G.AddEdge(vertices[w], vertices[v]); } while (G.E < E) { int v = StdRandom.Uniform(V); int w = StdRandom.Uniform(V); Edge e = new Edge(w, v); if ((v < w) && !set.Contains(e)) { set.Add(e); G.AddEdge(vertices[w], vertices[v]); } } return(G); }
private int count; // number of strongly-connected components /// <summary>Computes the strong components of the digraph <c>G</c>.</summary> /// <param name="G">the digraph</param> /// public KosarajuSharirSCC(Digraph G) { // compute reverse postorder of reverse graph DepthFirstOrder dfs = new DepthFirstOrder(G.Reverse()); // run DFS on G, using reverse postorder to guide calculation marked = new bool[G.V]; id = new int[G.V]; foreach (int v in dfs.ReversePost()) { if (!marked[v]) { this.dfs(G, v); count++; } } // check that id[] gives strong components Debug.Assert(check(G)); }
/************************************************************************** * * The code below is solely for testing correctness of the data type. * **************************************************************************/ // Determines whether a digraph has an Eulerian cycle using necessary // and sufficient conditions (without computing the cycle itself): // - at least one edge // - indegree(v) = outdegree(v) for every vertex // - the graph is connected, when viewed as an undirected graph // (ignoring isolated vertices) private static bool hasEulerianCycle(Digraph G) { // Condition 0: at least 1 edge if (G.E == 0) { return(false); } // Condition 1: indegree(v) == outdegree(v) for every vertex for (int v = 0; v < G.V; v++) { if (G.Outdegree(v) != G.Indegree(v)) { return(false); } } // Condition 2: graph is connected, ignoring isolated vertices Graph H = new Graph(G.V); for (int v = 0; v < G.V; v++) { foreach (int w in G.Adj(v)) { H.AddEdge(v, w); } } // check that all non-isolated vertices are conneted int s = nonIsolatedVertex(G); BreadthFirstPaths bfs = new BreadthFirstPaths(H, s); for (int v = 0; v < G.V; v++) { if (H.Degree(v) > 0 && !bfs.HasPathTo(v)) { return(false); } } return(true); }
// tournament /// <summary> /// Returns a random tournament digraph on <c>V</c> vertices. A tournament digraph /// is a DAG in which for every two vertices, there is one directed edge. /// A tournament is an oriented complete graph.</summary> /// <param name="V">the number of vertices</param> /// <returns>a random tournament digraph on <c>V</c> vertices</returns> /// public static Digraph Tournament(int V) { Digraph G = new Digraph(V); for (int v = 0; v < G.V; v++) { for (int w = v + 1; w < G.V; w++) { if (StdRandom.Bernoulli(0.5)) { G.AddEdge(v, w); } else { G.AddEdge(w, v); } } } return(G); }
public static void MainTest(string[] args) { string filename = args[0]; string delimiter = args[1]; SymbolDigraph sg = new SymbolDigraph(filename, delimiter); Digraph G = sg.G; string t = Console.ReadLine(); while (t != null) { if (sg.Contains(t)) { foreach (int v in G.Adj(sg.Index(t))) { Console.WriteLine(" " + sg.Name(v)); } } t = Console.ReadLine(); } }
/// <summary> /// Initializes a new digraph that is a deep copy of the specified digraph.</summary> /// <param name="G">the digraph to copy</param> /// public Digraph(Digraph G) : this(G.V) { numEdges = G.E; for (int v = 0; v < V; v++) { this.indegree[v] = G.Indegree(v); } for (int v = 0; v < G.V; v++) { // reverse so that adjacency list is in same order as original LinkedStack <int> reverse = new LinkedStack <int>(); foreach (int w in G.adj[v]) { reverse.Push(w); } foreach (int w in reverse) { adj[v].Add(w); } } }
private bool[] marked; // marked[v] = is there an s->v path? /// <summary> /// Computes the vertices reachable from the source vertex <c>s</c> in the /// digraph <c>G</c>.</summary> /// <param name="G">the digraph</param> /// <param name="s">the source vertex</param> /// public NonrecursiveDirectedDFS(Digraph G, int s) { marked = new bool[G.V]; // to be able to iterate over each adjacency list, keeping track of which // vertex in each adjacency list needs to be explored next IEnumerator <int>[] adj = new IEnumerator <int> [G.V]; for (int v = 0; v < G.V; v++) { adj[v] = G.Adj(v).GetEnumerator(); } // depth-first search using an explicit stack LinkedStack <int> stack = new LinkedStack <int>(); marked[s] = true; stack.Push(s); while (!stack.IsEmpty) { int v = stack.Peek(); if (adj[v].MoveNext()) { int w = adj[v].Current; // Console.Write("check {0}\n", w); if (!marked[w]) { // discovered vertex w for the first time marked[w] = true; // edgeTo[w] = v; stack.Push(w); // Console.Write("dfs({0})\n", w); } } else { // Console.Write("{0} done\n", v); stack.Pop(); } } }
// BFS from single source private void bfs(Digraph G, int s) { LinkedQueue <int> q = new LinkedQueue <int>(); marked[s] = true; distTo[s] = 0; q.Enqueue(s); while (!q.IsEmpty) { int v = q.Dequeue(); foreach (int w in G.Adj(v)) { if (!marked[w]) { edgeTo[w] = v; distTo[w] = distTo[v] + 1; marked[w] = true; q.Enqueue(w); } } } }
/// <summary> /// Computes the strong components of the digraph <c>G</c>.</summary> /// <param name="G">the digraph</param> /// public GabowSCC(Digraph G) { marked = new bool[G.V]; stack1 = new LinkedStack <int>(); stack2 = new LinkedStack <int>(); id = new int[G.V]; preorder = new int[G.V]; for (int v = 0; v < G.V; v++) { id[v] = -1; } for (int v = 0; v < G.V; v++) { if (!marked[v]) { dfs(G, v); } } // check that id[] gives strong components Debug.Assert(check(G)); }
internal static void UnitTest(Digraph G, String description) { Console.WriteLine(description); Console.WriteLine("-------------------------------------"); Console.Write(G); DirectedEulerianCycle euler = new DirectedEulerianCycle(G); Console.Write("Eulerian cycle: "); if (euler.HasEulerianCycle) { foreach (int v in euler.GetCycle()) { Console.Write(v + " "); } Console.WriteLine(); } else { Console.WriteLine("none"); } Console.WriteLine(); }
/// <summary> /// Returns an Eulerian path digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the path</param> /// <param name="E">the number of edges in the path</param> /// <returns>a digraph that is a directed Eulerian path on <c>V</c> vertices</returns> /// and <c>E</c> edges /// <exception cref="ArgumentException">if either V <= 0 or E < 0</exception> /// public static Digraph EulerianPath(int V, int E) { if (E < 0) { throw new ArgumentException("negative number of edges"); } if (V <= 0) { throw new ArgumentException("An Eulerian path must have at least one vertex"); } Digraph G = new Digraph(V); int[] vertices = new int[E + 1]; for (int i = 0; i < E + 1; i++) { vertices[i] = StdRandom.Uniform(V); } for (int i = 0; i < E; i++) { G.AddEdge(vertices[i], vertices[i + 1]); } return(G); }
/// <summary> /// Returns a random simple digraph on <c>V</c> vertices, with an /// edge between any two vertices with probability <c>p</c>. This is sometimes /// referred to as the Erdos-Renyi random digraph model. /// This implementations takes time propotional to V^2 (even if <c>p</c> is small).</summary> /// <param name="V">the number of vertices</param> /// <param name="p">the probability of choosing an edge</param> /// <returns>a random simple digraph on <c>V</c> vertices, with an edge between /// any two vertices with probability <c>p</c></returns> /// <exception cref="ArgumentException">if probability is not between 0 and 1</exception> /// public static Digraph Simple(int V, double p) { if (p < 0.0 || p > 1.0) { throw new ArgumentException("Probability must be between 0 and 1"); } Digraph G = new Digraph(V); for (int v = 0; v < V; v++) { for (int w = 0; w < V; w++) { if (v != w) { if (StdRandom.Bernoulli(p)) { G.AddEdge(v, w); } } } } return(G); }
/// <summary> /// Returns an Eulerian cycle digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the cycle</param> /// <param name="E">the number of edges in the cycle</param> /// <returns>a digraph that is a directed Eulerian cycle on <c>V</c> vertices /// and <c>E</c> edges</returns> /// <exception cref="ArgumentException">if either V <= 0 or E <= 0</exception> /// public static Digraph EulerianCycle(int V, int E) { if (E <= 0) { throw new ArgumentException("An Eulerian cycle must have at least one edge"); } if (V <= 0) { throw new ArgumentException("An Eulerian cycle must have at least one vertex"); } Digraph G = new Digraph(V); int[] vertices = new int[E]; for (int i = 0; i < E; i++) { vertices[i] = StdRandom.Uniform(V); } for (int i = 0; i < E - 1; i++) { G.AddEdge(vertices[i], vertices[i + 1]); } G.AddEdge(vertices[E - 1], vertices[0]); return(G); }
public static void MainTest(string[] args) { // read in digraph from command-line argument TextInput input = new TextInput(args[0]); Digraph G = new Digraph(input); DepthFirstOrder dfs = new DepthFirstOrder(G); Console.WriteLine(" v pre post"); Console.WriteLine("--------------"); for (int v = 0; v < G.V; v++) { Console.Write("{0,4} {1,4:} {2,4}\n", v, dfs.Pre(v), dfs.Post(v)); } Console.Write("Preorder: "); foreach (int v in dfs.Pre()) { Console.Write(v + " "); } Console.WriteLine(); Console.Write("Postorder: "); foreach (int v in dfs.Post()) { Console.Write(v + " "); } Console.WriteLine(); Console.Write("Reverse postorder: "); foreach (int v in dfs.ReversePost()) { Console.Write(v + " "); } Console.WriteLine(); }
private LinkedStack <int> path = null; // Eulerian path; null if no suh path /// <summary> /// Computes an Eulerian path in the specified digraph, if one exists.</summary> /// <param name="G">the digraph</param> /// public DirectedEulerianPath(Digraph G) { // find vertex from which to start potential Eulerian path: // a vertex v with outdegree(v) > indegree(v) if it exits; // otherwise a vertex with outdegree(v) > 0 int deficit = 0; int s = nonIsolatedVertex(G); for (int v = 0; v < G.V; v++) { if (G.Outdegree(v) > G.Indegree(v)) { deficit += (G.Outdegree(v) - G.Indegree(v)); s = v; } } // digraph can't have an Eulerian path // (this condition is needed) if (deficit > 1) { return; } // special case for digraph with zero edges (has a degenerate Eulerian path) if (s == -1) { s = 0; } // create local view of adjacency lists, to iterate one vertex at a time IEnumerator <int>[] adj = new IEnumerator <int> [G.V]; for (int v = 0; v < G.V; v++) { adj[v] = G.Adj(v).GetEnumerator(); } // greedily add to cycle, depth-first search style LinkedStack <int> stack = new LinkedStack <int>(); stack.Push(s); path = new LinkedStack <int>(); while (!stack.IsEmpty) { int v = stack.Pop(); while (adj[v].MoveNext()) { stack.Push(v); v = adj[v].Current; } // push vertex with no more available edges to path path.Push(v); } // check if all edges have been used if (path.Count != G.E + 1) { path = null; } Debug.Assert(check(G)); }
public static void MainTest(string[] args) { int V = int.Parse(args[0]); int E = int.Parse(args[1]); // Eulerian cycle Digraph G1 = DigraphGenerator.EulerianCycle(V, E); DirectedEulerianCycle.UnitTest(G1, "Eulerian cycle"); // Eulerian path Digraph G2 = DigraphGenerator.EulerianPath(V, E); DirectedEulerianCycle.UnitTest(G2, "Eulerian path"); // empty digraph Digraph G3 = new Digraph(V); DirectedEulerianCycle.UnitTest(G3, "empty digraph"); // self loop Digraph G4 = new Digraph(V); int v4 = StdRandom.Uniform(V); G4.AddEdge(v4, v4); DirectedEulerianCycle.UnitTest(G4, "single self loop"); // union of two disjoint cycles Digraph H1 = DigraphGenerator.EulerianCycle(V / 2, E / 2); Digraph H2 = DigraphGenerator.EulerianCycle(V - V / 2, E - E / 2); int[] perm = new int[V]; for (int i = 0; i < V; i++) { perm[i] = i; } StdRandom.Shuffle(perm); Digraph G5 = new Digraph(V); for (int v = 0; v < H1.V; v++) { foreach (int w in H1.Adj(v)) { G5.AddEdge(perm[v], perm[w]); } } for (int v = 0; v < H2.V; v++) { foreach (int w in H2.Adj(v)) { G5.AddEdge(perm[V / 2 + v], perm[V / 2 + w]); } } DirectedEulerianCycle.UnitTest(G5, "Union of two disjoint cycles"); // random digraph Digraph G6 = DigraphGenerator.Simple(V, E); DirectedEulerianCycle.UnitTest(G6, "simple digraph"); // 4-vertex digraph - no data file //Digraph G7 = new Digraph(new TextInput("eulerianD.txt")); //DirectedEulerianCycle.UnitTest(G7, "4-vertex Eulerian digraph"); }
private int count; // number of vertices reachable from s /// <summary> /// Computes the vertices in digraph <c>G</c> that are /// reachable from the source vertex <c>s</c>.</summary> /// <param name="G">the digraph</param> /// <param name="s">the source vertex</param> /// public DirectedDFS(Digraph G, int s) { marked = new bool[G.V]; dfs(G, s); }
/// <summary> /// Returns a random simple digraph on <c>V</c> vertices, <c>E</c> /// edges and (at least) <c>c</c> strong components. The vertices are randomly /// assigned integer labels between <c>0</c> and <c>c-1</c> (corresponding to /// strong components). Then, a strong component is creates among the vertices /// with the same label. Next, random edges (either between two vertices with /// the same labels or from a vetex with a smaller label to a vertex with a /// larger label). The number of components will be equal to the number of /// distinct labels that are assigned to vertices.</summary> /// <param name="V">the number of vertices</param> /// <param name="E">the number of edges</param> /// <param name="c">the (maximum) number of strong components</param> /// <returns>a random simple digraph on <c>V</c> vertices and /// <c>E</c> edges, with (at most) <c>c</c> strong components</returns> /// <exception cref="ArgumentException">if <c>c</c> is larger than <c>V</c></exception> /// public static Digraph Strong(int V, int E, int c) { if (c >= V || c <= 0) { throw new ArgumentException("Number of components must be between 1 and V"); } if (E <= 2 * (V - c)) { throw new ArgumentException("Number of edges must be at least 2(V-c)"); } if (E > (long)V * (V - 1) / 2) { throw new ArgumentException("Too many edges"); } // the digraph Digraph G = new Digraph(V); // edges added to G (to avoid duplicate edges) SET <Edge> set = new SET <Edge>(); int[] label = new int[V]; for (int v = 0; v < V; v++) { label[v] = StdRandom.Uniform(c); } // make all vertices with label c a strong component by // combining a rooted in-tree and a rooted out-tree for (int i = 0; i < c; i++) { // how many vertices in component c int count = 0; for (int v = 0; v < G.V; v++) { if (label[v] == i) { count++; } } // if (count == 0) System.err.println("less than desired number of strong components"); int[] vertices = new int[count]; int j = 0; for (int v = 0; v < V; v++) { if (label[v] == i) { vertices[j++] = v; } } StdRandom.Shuffle(vertices); // rooted-in tree with root = vertices[count-1] for (int v = 0; v < count - 1; v++) { int w = StdRandom.Uniform(v + 1, count); Edge e = new Edge(w, v); set.Add(e); G.AddEdge(vertices[w], vertices[v]); } // rooted-out tree with root = vertices[count-1] for (int v = 0; v < count - 1; v++) { int w = StdRandom.Uniform(v + 1, count); Edge e = new Edge(v, w); set.Add(e); G.AddEdge(vertices[v], vertices[w]); } } while (G.E < E) { int v = StdRandom.Uniform(V); int w = StdRandom.Uniform(V); Edge e = new Edge(v, w); if (!set.Contains(e) && v != w && label[v] <= label[w]) { set.Add(e); G.AddEdge(v, w); } } return(G); }
private LinkedStack <int> cycle; // the directed cycle; null if digraph is acyclic /// <summary> /// Determines whether the digraph <c>G</c> has a directed cycle and, if so, /// finds such a cycle.</summary> /// <param name="G">the digraph</param> /// public DirectedCycleX(Digraph G) { // indegrees of remaining vertices int[] indegree = new int[G.V]; for (int v = 0; v < G.V; v++) { indegree[v] = G.Indegree(v); } // initialize queue to contain all vertices with indegree = 0 LinkedQueue <int> queue = new LinkedQueue <int>(); for (int v = 0; v < G.V; v++) { if (indegree[v] == 0) { queue.Enqueue(v); } } for (int j = 0; !queue.IsEmpty; j++) { int v = queue.Dequeue(); foreach (int w in G.Adj(v)) { indegree[w]--; if (indegree[w] == 0) { queue.Enqueue(w); } } } // there is a directed cycle in subgraph of vertices with indegree >= 1. int[] edgeTo = new int[G.V]; int root = -1; // any vertex with indegree >= -1 for (int v = 0; v < G.V; v++) { if (indegree[v] == 0) { continue; } else { root = v; } foreach (int w in G.Adj(v)) { if (indegree[w] > 0) { edgeTo[w] = v; } } } if (root != -1) { // find any vertex on cycle bool[] visited = new bool[G.V]; while (!visited[root]) { visited[root] = true; root = edgeTo[root]; } // extract cycle cycle = new LinkedStack <int>(); int v = root; do { cycle.Push(v); v = edgeTo[v]; } while (v != root); cycle.Push(root); } Debug.Assert(check()); }