示例#1
0
        /**************************************************************************
        *
        *  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);
        }
示例#2
0
        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));
        }
示例#3
0
 // 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);
 }
示例#4
0
        /**************************************************************************
        *
        *  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);
        }
示例#5
0
        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));
        }