/************************************************************************** * * 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); }
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 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 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); }
/// <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 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)); }