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); }
private readonly int[] _rank; // rank[v] = order where vertex v appers in order /// <summary> /// Determines whether the digraph <tt>G</tt> has a topological order and, if so, /// finds such a topological order. /// </summary> /// <param name="g">g the digraph</param> public TopologicalX(Digraph g) { // indegrees of remaining vertices var indegree = new int[g.V]; for (var v = 0; v < g.V; v++) { indegree[v] = g.Indegree(v); } // initialize _rank = new int[g.V]; _order = new Collections.Queue <Integer>(); var count = 0; // initialize queue to contain all vertices with indegree = 0 var queue = new Collections.Queue <Integer>(); for (var v = 0; v < g.V; v++) { if (indegree[v] == 0) { queue.Enqueue(v); } } for (var 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; } //assert check(G); }
/// <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> /// Initializes a new digraph that is a deep copy of the specified digraph. /// </summary> /// <param name="g">g the digraph to copy</param> public Digraph(Digraph g) : this(g.V) { E = g.E; for (var v = 0; v < V; v++) { _indegree[v] = g.Indegree(v); } for (var v = 0; v < g.V; v++) { // reverse so that adjacency list is in same order as original var reverse = new Collections.Stack <Integer>(); foreach (int w in g._adj[v]) { reverse.Push(w); } foreach (int w in reverse) { _adj[v].Add(w); } } }
private readonly int[] _rank; // rank[v] = order where vertex v appers in order #endregion Fields #region Constructors /// <summary> /// Determines whether the digraph <tt>G</tt> has a topological order and, if so, /// finds such a topological order. /// </summary> /// <param name="g">g the digraph</param> public TopologicalX(Digraph g) { // indegrees of remaining vertices var indegree = new int[g.V]; for (var v = 0; v < g.V; v++) { indegree[v] = g.Indegree(v); } // initialize _rank = new int[g.V]; _order = new Collections.Queue<Integer>(); var count = 0; // initialize queue to contain all vertices with indegree = 0 var queue = new Collections.Queue<Integer>(); for (var v = 0; v < g.V; v++) if (indegree[v] == 0) queue.Enqueue(v); for (var 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; } //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; // the directed cycle; null if digraph is acyclic public DirectedCycleX(Digraph g) { // indegrees of remaining vertices var indegree = new int[g.V]; for (var v = 0; v < g.V; v++) { indegree[v] = g.Indegree(v); } // initialize queue to contain all vertices with indegree = 0 var queue = new Collections.Queue <Integer>(); for (var v = 0; v < g.V; v++) { if (indegree[v] == 0) { queue.Enqueue(v); } } for (var 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. var edgeTo = new int[g.V]; var root = -1; // any vertex with indegree >= -1 for (var v = 0; v < g.V; v++) { if (indegree[v] == 0) { continue; } root = v; foreach (int w in g.Adj(v)) { if (indegree[w] > 0) { edgeTo[w] = v; } } } if (root != -1) { // find any vertex on cycle var visited = new bool[g.V]; while (!visited[root]) { visited[root] = true; root = edgeTo[root]; } // extract cycle _cycle = new Collections.Stack <Integer>(); var v = root; do { _cycle.Push(v); v = edgeTo[v]; } while (v != root); _cycle.Push(root); } //assert check(); }
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); }
/// <summary> /// Initializes a new digraph that is a deep copy of the specified digraph. /// </summary> /// <param name="g">g the digraph to copy</param> public Digraph(Digraph g) : this(g.V) { E = g.E; for (var v = 0; v < V; v++) _indegree[v] = g.Indegree(v); for (var v = 0; v < g.V; v++) { // reverse so that adjacency list is in same order as original var reverse = new Collections.Stack<Integer>(); foreach (int w in g._adj[v]) { reverse.Push(w); } foreach (int w in reverse) { _adj[v].Add(w); } } }
private readonly Collections.Stack<Integer> _cycle; // the directed cycle; null if digraph is acyclic #endregion Fields #region Constructors public DirectedCycleX(Digraph g) { // indegrees of remaining vertices var indegree = new int[g.V]; for (var v = 0; v < g.V; v++) { indegree[v] = g.Indegree(v); } // initialize queue to contain all vertices with indegree = 0 var queue = new Collections.Queue<Integer>(); for (var v = 0; v < g.V; v++) if (indegree[v] == 0) queue.Enqueue(v); for (var 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. var edgeTo = new int[g.V]; var root = -1; // any vertex with indegree >= -1 for (var v = 0; v < g.V; v++) { if (indegree[v] == 0) continue; root = v; foreach (int w in g.Adj(v)) { if (indegree[w] > 0) { edgeTo[w] = v; } } } if (root != -1) { // find any vertex on cycle var visited = new bool[g.V]; while (!visited[root]) { visited[root] = true; root = edgeTo[root]; } // extract cycle _cycle = new Collections.Stack<Integer>(); var v = root; do { _cycle.Push(v); v = edgeTo[v]; } while (v != root); _cycle.Push(root); } //assert check(); }