/************************************************************************** * * 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)); }
// returns any non-isolated vertex; -1 if no such vertex private static int nonIsolatedVertex(Digraph G) { for (int v = 0; v < G.V; v++) { if (G.Outdegree(v) > 0) { return(v); } } return(-1); }
/************************************************************************** * * 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); }
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)); }