private void dfs(Digraph G, int v) { marked[v] = true; low[v] = pre++; int min = low[v]; stack.Push(v); foreach (int w in G.Adj(v)) { if (!marked[w]) { dfs(G, w); } if (low[w] < min) { min = low[w]; } } if (min < low[v]) { low[v] = min; return; } int u; do { u = stack.Pop(); id[u] = count; low[u] = G.V; } while (u != v); count++; }
// check that algorithm computes either the topological order or finds a directed cycle private void dfs(Digraph G, int v) { onStack[v] = true; marked[v] = true; foreach (int w in G.Adj(v)) { // short circuit if directed cycle found if (cycle != null) { return; } else if (!marked[w]) { // found new vertex, so recur edgeTo[w] = v; dfs(G, w); } else if (onStack[w]) { // trace back directed cycle cycle = new LinkedStack <int>(); for (int x = v; x != w; x = edgeTo[x]) { cycle.Push(x); } cycle.Push(w); cycle.Push(v); Debug.Assert(check()); } } onStack[v] = false; }
// BFS from multiple sources private void bfs(Digraph G, IEnumerable <int> sources) { LinkedQueue <int> q = new LinkedQueue <int>(); foreach (int s in sources) { 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); } } } }
private void dfs(Digraph G, int v) { marked[v] = true; preorder[v] = pre++; stack1.Push(v); stack2.Push(v); foreach (int w in G.Adj(v)) { if (!marked[w]) { dfs(G, w); } else if (id[w] == -1) { while (preorder[stack2.Peek()] > preorder[w]) { stack2.Pop(); } } } // found strong component containing v if (stack2.Peek() == v) { stack2.Pop(); int w; do { w = stack1.Pop(); id[w] = count; } while (w != v); count++; } }
private LinkedStack <int> cycle = null; // Eulerian cycle; null if no such cylce /// <summary> /// Computes an Eulerian cycle in the specified digraph, if one exists. /// </summary> /// <param name="G">the digraph</param> /// public DirectedEulerianCycle(Digraph G) { // must have at least one edge if (G.E == 0) { return; } // necessary condition: indegree(v) = outdegree(v) for each vertex v // (without this check, DFS might return a path instead of a cycle) for (int v = 0; v < G.V; v++) { if (G.Outdegree(v) != G.Indegree(v)) { return; } } // 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(); } // initialize stack with any non-isolated vertex int s = nonIsolatedVertex(G); LinkedStack <int> stack = new LinkedStack <int>(); stack.Push(s); // greedily add to putative cycle, depth-first search style cycle = new LinkedStack <int>(); while (!stack.IsEmpty) { int v = stack.Pop(); while (adj[v].MoveNext()) { stack.Push(v); v = adj[v].Current; } // add vertex with no more leaving edges to cycle cycle.Push(v); } // check if all edges have been used // (in case there are two or more vertex-disjoint Eulerian cycles) if (cycle.Count != G.E + 1) { cycle = null; } Debug.Assert(certifySolution(G)); }
private void dfs(Digraph G, int v) { count++; marked[v] = true; foreach (int w in G.Adj(v)) { if (!marked[w]) { dfs(G, w); } } }
private void dfs(Digraph G, int v) { marked[v] = true; foreach (int w in G.Adj(v)) { if (!marked[w]) { edgeTo[w] = v; dfs(G, w); } } }
// certify that digraph is acyclic private bool check(Digraph G) { // digraph is acyclic if (HasOrder) { // check that ranks are a permutation of 0 to V-1 bool[] found = new bool[G.V]; for (int i = 0; i < G.V; i++) { found[Rank(i)] = true; } for (int i = 0; i < G.V; i++) { if (!found[i]) { Console.Error.WriteLine("No vertex with rank " + i); return(false); } } // check that ranks provide a valid topological order for (int v = 0; v < G.V; v++) { foreach (int w in G.Adj(v)) { if (Rank(v) > Rank(w)) { Console.Error.WriteLine("{0}-{1}: rank({2}) = {3}, rank({4}) = {5}\n", v, w, v, Rank(v), w, Rank(w)); return(false); } } } // check that order() is consistent with rank() int r = 0; foreach (int v in Order()) { if (Rank(v) != r) { Console.Error.WriteLine("Order() and Rank() inconsistent"); return(false); } r++; } } return(true); }
// run DFS in digraph G from vertex v and compute preorder/postorder private void dfs(Digraph G, int v) { marked[v] = true; pre[v] = preCounter++; preorder.Enqueue(v); foreach (int w in G.Adj(v)) { if (!marked[w]) { dfs(G, w); } } postorder.Enqueue(v); post[v] = postCounter++; }
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)); }
/************************************************************************** * * 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); }
/************************************************************************** * * 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); }
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(); } }
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(); } } }
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 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()); }
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)); }