private void dfs(Graph G, int v) { marked[v] = true; foreach (int w in G.Adj(v)) { // short circuit if odd-length cycle found if (cycle != null) { return; } // found uncolored vertex, so recur if (!marked[w]) { edgeTo[w] = v; color[w] = !color[v]; dfs(G, w); } // if v-w create an odd-length cycle, find it else if (color[w] == color[v]) { isBipartite = false; cycle = new LinkedStack <int>(); cycle.Push(w); // don't need this unless you want to include start vertex twice for (int x = v; x != w; x = edgeTo[x]) { cycle.Push(x); } cycle.Push(w); } } }
// does this graph have two parallel edges? // side effect: initialize cycle to be two parallel edges private bool hasParallelEdges(Graph G) { marked = new bool[G.V]; for (int v = 0; v < G.V; v++) { // check for parallel edges incident to v foreach (int w in G.Adj(v)) { if (marked[w]) { cycle = new LinkedStack <int>(); cycle.Push(v); cycle.Push(w); cycle.Push(v); return(true); } marked[w] = true; } // reset so marked[v] = false for all v foreach (int w in G.Adj(v)) { marked[w] = false; } } return(false); }
// 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; }
private void dfs(Graph G, int u, int v) { marked[v] = true; foreach (int w in G.Adj(v)) { // short circuit if cycle already found if (cycle != null) { return; } if (!marked[w]) { edgeTo[w] = v; dfs(G, v, w); } // check for cycle (but disregard reverse of edge leading to v) else if (w != u) { cycle = new LinkedStack <int>(); for (int x = v; x != w; x = edgeTo[x]) { cycle.Push(x); } cycle.Push(w); cycle.Push(v); } } }
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 bfs(Graph G, int s) { LinkedQueue <int> q = new LinkedQueue <int>(); color[s] = WHITE; marked[s] = true; q.Enqueue(s); while (!q.IsEmpty) { int v = q.Dequeue(); foreach (int w in G.Adj(v)) { if (!marked[w]) { marked[w] = true; edgeTo[w] = v; color[w] = !color[v]; q.Enqueue(w); } else if (color[w] == color[v]) { isBipartite = false; // to form odd cycle, consider s-v path and s-w path // and let x be closest node to v and w common to two paths // then (w-x path) + (x-v path) + (edge v-w) is an odd-length cycle // Note: distTo[v] == distTo[w]; cycle = new LinkedQueue <int>(); LinkedStack <int> stack = new LinkedStack <int>(); int x = v, y = w; while (x != y) { stack.Push(x); cycle.Enqueue(y); x = edgeTo[x]; y = edgeTo[y]; } stack.Push(x); while (!stack.IsEmpty) { cycle.Enqueue(stack.Pop()); } cycle.Enqueue(w); return; } } } }
/// <summary> /// Returns a path between the source vertex <c>s</c> and vertex <c>v</c>, or /// <c>null</c> if no such path.</summary> /// <param name="v">the vertex</param> /// <returns>the sequence of vertices on a path between the source vertex /// <c>s</c> and vertex <c>v</c>, as an IEnumerable</returns> /// public IEnumerable <int> PathTo(int v) { if (!HasPathTo(v)) { return(null); } LinkedStack <int> path = new LinkedStack <int>(); for (int x = v; x != s; x = edgeTo[x]) { path.Push(x); } path.Push(s); return(path); }
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++; }
public static void MainTest(string[] args) { int M = int.Parse(args[0]); MinPQ <Transaction> pq = new MinPQ <Transaction>(M + 1); TextInput StdIn = new TextInput(); while (!StdIn.IsEmpty) { // Create an entry from the next line and put on the PQ. string line = StdIn.ReadLine(); Transaction transaction = new Transaction(line); pq.Insert(transaction); // remove minimum if M+1 entries on the PQ if (pq.Count > M) { pq.DelMin(); } } // top M entries are on the PQ // print entries on PQ in reverse order LinkedStack <Transaction> stack = new LinkedStack <Transaction>(); foreach (Transaction transaction in pq) { stack.Push(transaction); } foreach (Transaction transaction in stack) { Console.WriteLine(transaction); } }
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++; } }
// additional test static void TopInts() { int[] allInts = { 12, 11, 8, 7, 9, 5, 4, 3, 2, 29, 23, 1, 24, 30, 9, 4, 88, 5, 100, 29, 23, 5, 99, 87, 22, 111 }; MinPQ <int> pq0 = new MinPQ <int>(allInts); int M = allInts.Length / 3; MinPQ <int> pq = new MinPQ <int>(M + 1); Console.WriteLine("Top {0} is ", M); foreach (var n in allInts) { pq.Insert(n); Console.WriteLine("Min is {0}", pq.Min); // remove minimum if M+1 entries on the PQ if (pq.Count > M) { pq.DelMin(); } } // print entries on PQ in reverse order LinkedStack <int> stack = new LinkedStack <int>(); foreach (int n in pq) { stack.Push(n); } foreach (int n in stack) { Console.WriteLine(n); } Console.WriteLine("These are the top elements"); }
// does this graph have a self loop? // side effect: initialize cycle to be self loop private bool hasSelfLoop(Graph G) { for (int v = 0; v < G.V; v++) { foreach (int w in G.Adj(v)) { if (v == w) { cycle = new LinkedStack <int>(); cycle.Push(v); cycle.Push(v); return(true); } } } return(false); }
private readonly int s; // source vertex /// <summary> /// Computes the vertices connected to the source vertex <c>s</c> in the graph <c>G</c>.</summary> /// <param name="G">the graph</param> /// <param name="s">the source vertex</param> /// public NonrecursiveDFS(Graph G, int s) { this.s = s; marked = new bool[G.V]; edgeTo = new int[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); //Console.Write("Visiting ({0})\n", s); while (!stack.IsEmpty) { int v = stack.Peek(); if (adj[v].MoveNext()) { int w = adj[v].Current; //Console.Write("Approaching {0}\n", w); if (!marked[w]) { // discovered vertex w for the first time marked[w] = true; edgeTo[w] = v; stack.Push(w); //Console.Write("Visiting ({0})\n", w); } //else // Console.Write("Visited {0}\n", w); } else { //Console.Write("Returning from {0}\n", stack.Peek()); stack.Pop(); } } }
/// <summary> /// Returns the extreme points on the convex hull in counterclockwise order.</summary> /// <returns>the extreme points on the convex hull in counterclockwise order</returns> /// public IEnumerable <Point2D> Hull() { LinkedStack <Point2D> s = new LinkedStack <Point2D>(); foreach (Point2D p in hull) { s.Push(p); } return(s); }
/// <summary> /// Returns the vertices in reverse postorder.</summary> /// <returns>the vertices in reverse postorder, as an iterable of vertices</returns> /// public IEnumerable <int> ReversePost() { LinkedStack <int> reverse = new LinkedStack <int>(); foreach (int v in postorder) { reverse.Push(v); } return(reverse); }
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(); } } }
private int M; // number of characters in regular expression /// <summary>Initializes the NFA from the specified regular expression.</summary> /// <param name="regexp">the regular expression</param> /// <exception cref="ArgumentException">if the regular expression is invalid</exception> /// public NFA(string regexp) { this.regexp = regexp; M = regexp.Length; LinkedStack <int> ops = new LinkedStack <int>(); G = new Digraph(M + 1); for (int i = 0; i < M; i++) { int lp = i; if (regexp[i] == '(' || regexp[i] == '|') { ops.Push(i); } else if (regexp[i] == ')') { int or = ops.Pop(); // 2-way or operator if (regexp[or] == '|') { lp = ops.Pop(); G.AddEdge(lp, or + 1); G.AddEdge(or, i); } else if (regexp[or] == '(') { lp = or; } else { Debug.Assert(false); } } // closure operator (uses 1-character lookahead) if (i < M - 1 && regexp[i + 1] == '*') { G.AddEdge(lp, i + 1); G.AddEdge(i + 1, lp); } if (regexp[i] == '(' || regexp[i] == '*' || regexp[i] == ')') { G.AddEdge(i, i + 1); } } if (ops.Count != 0) { throw new ArgumentException("Invalid regular expression"); } }
/// <summary> /// Returns a longest path from the source vertex <c>s</c> to vertex <c>v</c>.</summary> /// <param name="v">the destination vertex</param> /// <returns>a longest path from the source vertex <c>s</c> to vertex <c>v</c></returns> /// as an iterable of edges, and <c>null</c> if no such path /// public IEnumerable <DirectedEdge> PathTo(int v) { if (!HasPathTo(v)) { return(null); } LinkedStack <DirectedEdge> path = new LinkedStack <DirectedEdge>(); for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.From]) { path.Push(e); } return(path); }
// check that algorithm computes either the topological order or finds a directed cycle private void dfs(EdgeWeightedDigraph G, int v) { onStack[v] = true; marked[v] = true; foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; // short circuit if directed cycle found if (cycle != null) { return; } else if (!marked[w]) { //found new vertex, so recur edgeTo[w] = e; dfs(G, w); } else if (onStack[w]) { // trace back directed cycle cycle = new LinkedStack <DirectedEdge>(); DirectedEdge eTemp = e; while (eTemp.From != w) { cycle.Push(eTemp); eTemp = edgeTo[eTemp.From]; } cycle.Push(eTemp); return; } } onStack[v] = false; }
/// <summary> /// Returns a shortest path between the source vertex <c>s</c> and vertex <c>v</c>.</summary> /// <param name="v">the destination vertex</param> /// <returns>a shortest path between the source vertex <c>s</c> and vertex <c>v</c>; /// <c>null</c> if no such path</returns> /// public IEnumerable <Edge> PathTo(int v) { if (!HasPathTo(v)) { return(null); } LinkedStack <Edge> path = new LinkedStack <Edge>(); int x = v; for (Edge e = edgeTo[v]; e != null; e = edgeTo[x]) { path.Push(e); x = e.Other(x); } return(path); }
/// <summary> /// Initializes a new graph that is a deep copy of <c>G</c>.</summary> /// <param name="G">the graph to copy</param> /// public Graph(Graph G) : this(G.V) { numEdges = G.E; 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); } } }
/// <summary> /// Returns a shortest path from vertex <c>s</c> to vertex <c>t</c>.</summary> /// <param name="s">the source vertex</param> /// <param name="t">the destination vertex</param> /// <returns>a shortest path from vertex <c>s</c> to vertex <c>t</c> /// as an iterable of edges, and <c>null</c> if no such path</returns> /// <exception cref="InvalidOperationException">if there is a negative cost cycle</exception> /// public IEnumerable <DirectedEdge> Path(int s, int t) { if (HasNegativeCycle) { throw new InvalidOperationException("Negative cost cycle exists"); } if (!HasPath(s, t)) { return(null); } LinkedStack <DirectedEdge> path = new LinkedStack <DirectedEdge>(); for (DirectedEdge e = edgeTo[s, t]; e != null; e = edgeTo[s, e.From]) { path.Push(e); } return(path); }
public static void MainTest(string[] args) { LinkedStack <string> s = new LinkedStack <string>(); TextInput StdIn = new TextInput(); while (!StdIn.IsEmpty) { string item = StdIn.ReadString(); if (!item.Equals("-")) { s.Push(item); } else if (!s.IsEmpty) { Console.Write(s.Pop() + " "); } } Console.WriteLine("(" + s.Count + " left on stack)"); }
/// <summary> /// Computes the convex hull of the specified array of points. /// </summary> /// <param name="pts">the array of points</param> /// <exception cref="NullReferenceException">if <c>points</c> is <c>null</c> or if any /// entry in <c>points[]</c> is <c>null</c></exception> /// public GrahamScan(Point2D[] pts) { // defensive copy int N = pts.Length; Point2D[] points = new Point2D[N]; for (int i = 0; i < N; i++) { points[i] = pts[i]; } // preprocess so that points[0] has lowest y-coordinate; break ties by x-coordinate // points[0] is an extreme point of the convex hull // (alternatively, could do easily in linear time) Array.Sort(points); // sort by polar angle with respect to base point points[0], // breaking ties by distance to points[0] Array.Sort(points, 1, N - 1, points[0].GetPolarOrder()); hull.Push(points[0]); // p[0] is first extreme point // find index k1 of first point not equal to points[0] int k1; for (k1 = 1; k1 < N; k1++) { if (!points[0].Equals(points[k1])) { break; } } if (k1 == N) { return; // all points equal } // find index k2 of first point not collinear with points[0] and points[k1] int k2; for (k2 = k1 + 1; k2 < N; k2++) { if (Point2D.Ccw(points[0], points[k1], points[k2]) != 0) { break; } } hull.Push(points[k2 - 1]); // points[k2-1] is second extreme point // Graham scan; note that points[N-1] is extreme point different from points[0] for (int i = k2; i < N; i++) { Point2D top = hull.Pop(); while (Point2D.Ccw(hull.Peek(), top, points[i]) <= 0) { top = hull.Pop(); } hull.Push(top); hull.Push(points[i]); } Debug.Assert(isConvex()); }
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)); }
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 int[] distTo; // distTo[v] = number of edges on shortest path to v /// <summary> /// Determines a maximum matching (and a minimum vertex cover) /// in a bipartite graph.</summary> /// <param name="G">the bipartite graph</param> /// <exception cref="ArgumentException">if <c>G</c> is not bipartite</exception> /// public HopcroftKarp(Graph G) { bipartition = new BipartiteX(G); if (!bipartition.IsBipartite) { throw new ArgumentException("graph is not bipartite"); } // initialize empty matching this.V = G.V; mate = new int[V]; for (int v = 0; v < V; v++) { mate[v] = UNMATCHED; } // the call to hasAugmentingPath() provides enough info to reconstruct level graph while (hasAugmentingPath(G)) { // 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(); } // for each unmatched vertex s on one side of bipartition for (int s = 0; s < V; s++) { if (IsMatched(s) || !bipartition.Color(s)) { continue; // or use distTo[s] == 0 } // find augmenting path from s using nonrecursive DFS LinkedStack <int> path = new LinkedStack <int>(); path.Push(s); while (!path.IsEmpty) { int v = path.Peek(); // retreat, no more edges in level graph leaving v if (!adj[v].MoveNext()) { path.Pop(); } // advance else { // process edge v-w only if it is an edge in level graph int w = adj[v].Current; if (!isLevelGraphEdge(v, w)) { continue; } // add w to augmenting path path.Push(w); // augmenting path found: update the matching if (!IsMatched(w)) { // Console.WriteLine("augmenting path: " + toString(path)); while (!path.IsEmpty) { int x = path.Pop(); int y = path.Pop(); mate[x] = y; mate[y] = x; } cardinality++; } } } } } // also find a min vertex cover inMinVertexCover = new bool[V]; for (int v = 0; v < V; v++) { if (bipartition.Color(v) && !marked[v]) { inMinVertexCover[v] = true; } if (!bipartition.Color(v) && marked[v]) { inMinVertexCover[v] = true; } } Debug.Assert(certifySolution(G)); }
/// <summary> /// Computes an Eulerian path in the specified graph, if one exists.</summary> /// <param name="G">the graph</param> /// public EulerianPath(Graph G) { // find vertex from which to start potential Eulerian path: // a vertex v with odd degree(v) if it exits; // otherwise a vertex with degree(v) > 0 int oddDegreeVertices = 0; int s = nonIsolatedVertex(G); for (int v = 0; v < G.V; v++) { if (G.Degree(v) % 2 != 0) { oddDegreeVertices++; s = v; } } // graph can't have an Eulerian path // (this condition is needed for correctness) if (oddDegreeVertices > 2) { return; } // special case for graph 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 // the helper Edge data type is used to avoid exploring both copies of an edge v-w LinkedQueue <Edge>[] adj = new LinkedQueue <Edge> [G.V]; for (int v = 0; v < G.V; v++) { adj[v] = new LinkedQueue <Edge>(); } for (int v = 0; v < G.V; v++) { int selfLoops = 0; foreach (int w in G.Adj(v)) { // careful with self loops if (v == w) { if (selfLoops % 2 == 0) { Edge e = new Edge(v, w); adj[v].Enqueue(e); adj[w].Enqueue(e); } selfLoops++; } else if (v < w) { Edge e = new Edge(v, w); adj[v].Enqueue(e); adj[w].Enqueue(e); } } } // initialize stack with any non-isolated vertex LinkedStack <int> stack = new LinkedStack <int>(); stack.Push(s); // greedily search through edges in iterative DFS style path = new LinkedStack <int>(); while (!stack.IsEmpty) { int v = stack.Pop(); while (!adj[v].IsEmpty) { Edge edge = adj[v].Dequeue(); if (edge.IsUsed) { continue; } edge.IsUsed = true; stack.Push(v); v = edge.Other(v); } // push vertex with no more leaving edges to path path.Push(v); } // check if all edges are used if (path.Count != G.E + 1) { path = null; } Debug.Assert(certifySolution(G)); }
/// <summary> /// Computes an Eulerian cycle in the specified graph, if one exists.</summary> /// <param name="G">the graph</param> /// public EulerianCycle(Graph G) { // must have at least one edge if (G.E == 0) { return; } // necessary condition: all vertices have even degree // (this test is needed or it might find an Eulerian path instead of cycle) for (int v = 0; v < G.V; v++) { if (G.Degree(v) % 2 != 0) { return; } } // create local view of adjacency lists, to iterate one vertex at a time // the helper Edge data type is used to avoid exploring both copies of an edge v-w LinkedQueue <Edge>[] adj = new LinkedQueue <Edge> [G.V]; for (int v = 0; v < G.V; v++) { adj[v] = new LinkedQueue <Edge>(); } for (int v = 0; v < G.V; v++) { int selfLoops = 0; foreach (int w in G.Adj(v)) { // careful with self loops if (v == w) { if (selfLoops % 2 == 0) { Edge e = new Edge(v, w); adj[v].Enqueue(e); adj[w].Enqueue(e); } selfLoops++; } else if (v < w) { Edge e = new Edge(v, w); adj[v].Enqueue(e); adj[w].Enqueue(e); } } } // initialize stack with any non-isolated vertex int s = nonIsolatedVertex(G); LinkedStack <int> stack = new LinkedStack <int>(); stack.Push(s); // greedily search through edges in iterative DFS style cycle = new LinkedStack <int>(); while (!stack.IsEmpty) { int v = stack.Pop(); while (!adj[v].IsEmpty) { Edge edge = adj[v].Dequeue(); if (edge.IsUsed) { continue; } edge.IsUsed = true; stack.Push(v); v = edge.Other(v); } // push vertex with no more leaving edges to cycle cycle.Push(v); } // check if all edges are used if (cycle.Count != G.E + 1) { cycle = null; } Debug.Assert(certifySolution(G)); }