private readonly Collections.Stack<Integer> _path; // Eulerian path; null if no suh path #endregion Fields #region Constructors /// <summary> /// Computes an Eulerian path in the specified digraph, if one exists. /// </summary> /// <param name="g">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 var deficit = 0; var s = NonIsolatedVertex(g); for (var 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 var adj = new IEnumerator<Integer>[g.V]; for (var v = 0; v < g.V; v++) adj[v] = g.Adj(v).GetEnumerator(); // greedily add to cycle, depth-first search style var stack = new Collections.Stack<Integer>(); stack.Push(s); _path = new Collections.Stack<Integer>(); 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.Size() != g.E + 1) _path = null; //assert check(G); }
/// <summary> /// 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. /// </summary> /// <param name="g"></param> /// <returns></returns> 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 var deficit = 0; for (var 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 var h = new Graph(g.V); for (var 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 var s = NonIsolatedVertex(g); var bfs = new BreadthFirstPaths(h, s); for (var v = 0; v < g.V; v++) { if (h.Degree(v) > 0 && !bfs.HasPathTo(v)) { return(false); } } return(true); }
private readonly Collections.Stack <Integer> _cycle; // Eulerian cycle; null if no such cylce /// <summary> /// Computes an Eulerian cycle in the specified digraph, if one exists. /// </summary> /// <param name="g">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 (var 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 var adj = new IEnumerator <Integer> [g.V]; for (var v = 0; v < g.V; v++) { adj[v] = g.Adj(v).GetEnumerator(); } // initialize stack with any non-isolated vertex var s = NonIsolatedVertex(g); var stack = new Collections.Stack <Integer>(); stack.Push(s); // greedily add to putative cycle, depth-first search style _cycle = new Collections.Stack <Integer>(); 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.Size() != g.E + 1) { _cycle = null; } //assert certifySolution(G); }
/// <summary> /// returns any non-isolated vertex; -1 if no such vertex /// </summary> /// <param name="g"></param> /// <returns></returns> private static int NonIsolatedVertex(Digraph g) { for (var v = 0; v < g.V; v++) { if (g.Outdegree(v) > 0) { return(v); } } return(-1); }
/// <summary> /// 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) /// </summary> /// <param name="g"></param> /// <returns></returns> 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 (var v = 0; v < g.V; v++) { if (g.Outdegree(v) != g.Indegree(v)) { return(false); } } // Condition 2: graph is connected, ignoring isolated vertices var h = new Graph(g.V); for (var 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 var s = NonIsolatedVertex(g); var bfs = new BreadthFirstPaths(h, s); for (var v = 0; v < g.V; v++) { if (h.Degree(v) > 0 && !bfs.HasPathTo(v)) { return(false); } } return(true); }
/// <summary> /// returns any non-isolated vertex; -1 if no such vertex /// </summary> /// <param name="g"></param> /// <returns></returns> private static int NonIsolatedVertex(Digraph g) { for (var v = 0; v < g.V; v++) if (g.Outdegree(v) > 0) return v; return -1; }
/// <summary> /// 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. /// </summary> /// <param name="g"></param> /// <returns></returns> 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 var deficit = 0; for (var 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 var h = new Graph(g.V); for (var 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 var s = NonIsolatedVertex(g); var bfs = new BreadthFirstPaths(h, s); for (var v = 0; v < g.V; v++) if (h.Degree(v) > 0 && !bfs.HasPathTo(v)) return false; return true; }
private readonly Collections.Stack <Integer> _path; // Eulerian path; null if no suh path /// <summary> /// Computes an Eulerian path in the specified digraph, if one exists. /// </summary> /// <param name="g">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 var deficit = 0; var s = NonIsolatedVertex(g); for (var 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 var adj = new IEnumerator <Integer> [g.V]; for (var v = 0; v < g.V; v++) { adj[v] = g.Adj(v).GetEnumerator(); } // greedily add to cycle, depth-first search style var stack = new Collections.Stack <Integer>(); stack.Push(s); _path = new Collections.Stack <Integer>(); 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.Size() != g.E + 1) { _path = null; } //assert check(G); }