Ejemplo n.º 1
0
        private int[] rank;              // rank[v] = order where vertex v appers in order

        /// <summary>
        /// Determines whether the digraph <c>G</c> has a topological order and, if so,
        /// finds such a topological order.
        /// </summary>
        /// <param name="G">the digraph</param>
        ///
        public TopologicalX(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
            rank  = new int[G.V];
            order = new LinkedQueue <int>();
            int count = 0;

            // 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();
                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;
            }

            Debug.Assert(check(G));
        }
Ejemplo n.º 2
0
        public static void MainTest(string[] args)
        {
            int V = int.Parse(args[0]);
            int E = int.Parse(args[1]);

            // Eulerian cycle
            Digraph G1 = DigraphGenerator.EulerianCycle(V, E);

            DirectedEulerianPath.UnitTest(G1, "Eulerian cycle");

            // Eulerian path
            Digraph G2 = DigraphGenerator.EulerianPath(V, E);

            DirectedEulerianPath.UnitTest(G2, "Eulerian path");

            // add one random edge
            Digraph G3 = new Digraph(G2);

            G3.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V));
            DirectedEulerianPath.UnitTest(G3, "one random edge added to Eulerian path");

            // self loop
            Digraph G4 = new Digraph(V);
            int     v4 = StdRandom.Uniform(V);

            G4.AddEdge(v4, v4);
            DirectedEulerianPath.UnitTest(G4, "single self loop");

            // single edge
            Digraph G5 = new Digraph(V);

            G5.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V));
            DirectedEulerianPath.UnitTest(G5, "single edge");

            // empty digraph
            Digraph G6 = new Digraph(V);

            DirectedEulerianPath.UnitTest(G6, "empty digraph");

            // random digraph
            Digraph G7 = DigraphGenerator.Simple(V, E);

            DirectedEulerianPath.UnitTest(G7, "simple digraph");

            // 4-vertex digraph
            //Digraph G8 = new Digraph(new TextInput("eulerianD.txt"));
            //DirectedEulerianPath.UnitTest(G8, "4-vertex Eulerian digraph");
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        public static void MainTest(string[] args)
        {
            TextInput input             = new TextInput(args[0]);
            Digraph   G                 = new Digraph(input);
            int       s                 = int.Parse(args[1]);
            NonrecursiveDirectedDFS dfs = new NonrecursiveDirectedDFS(G, s);

            for (int v = 0; v < G.V; v++)
            {
                if (dfs.Marked(v))
                {
                    Console.Write(v + " ");
                }
            }
            Console.WriteLine();
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Returns a path digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the path</param>
        /// <returns>a digraph that is a directed path on <c>V</c> vertices</returns>
        ///
        public static Digraph Path(int V)
        {
            Digraph G = new Digraph(V);

            int[] vertices = new int[V];
            for (int i = 0; i < V; i++)
            {
                vertices[i] = i;
            }
            StdRandom.Shuffle(vertices);
            for (int i = 0; i < V - 1; i++)
            {
                G.AddEdge(vertices[i], vertices[i + 1]);
            }
            return(G);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Returns a complete binary tree digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the binary tree</param>
        /// <returns>a digraph that is a complete binary tree on <c>V</c> vertices</returns>
        ///
        public static Digraph BinaryTree(int V)
        {
            Digraph G = new Digraph(V);

            int[] vertices = new int[V];
            for (int i = 0; i < V; i++)
            {
                vertices[i] = i;
            }
            StdRandom.Shuffle(vertices);
            for (int i = 1; i < V; i++)
            {
                G.AddEdge(vertices[i], vertices[(i - 1) / 2]);
            }
            return(G);
        }
Ejemplo n.º 7
0
        private int[] rank;              // rank[v] = position of vertex v in topological order

        /// <summary>
        /// Determines whether the digraph <c>G</c> has a topological order and, if so,
        /// finds such a topological order.</summary>
        /// <param name="G">the digraph</param>
        ///
        public Topological(Digraph G)
        {
            DirectedCycle finder = new DirectedCycle(G);

            if (!finder.HasCycle)
            {
                DepthFirstOrder dfs = new DepthFirstOrder(G);
                order = dfs.ReversePost();
                rank  = new int[G.V];
                int i = 0;
                foreach (int v in order)
                {
                    rank[v] = i++;
                }
            }
        }
Ejemplo n.º 8
0
        // does the id[] array contain the strongly connected components?
        private bool check(Digraph G)
        {
            TransitiveClosure tc = new TransitiveClosure(G);

            for (int v = 0; v < G.V; v++)
            {
                for (int w = 0; w < G.V; w++)
                {
                    if (StronglyConnected(v, w) != (tc.Reachable(v, w) && tc.Reachable(w, v)))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Ejemplo n.º 9
0
        /// <summary>Computes the strong components of the digraph <c>G</c>.</summary>
        /// <param name="G">the digraph</param>
        ///
        public TarjanSCC(Digraph G)
        {
            marked = new bool[G.V];
            stack  = new LinkedStack <int>();
            id     = new int[G.V];
            low    = new int[G.V];
            for (int v = 0; v < G.V; v++)
            {
                if (!marked[v])
                {
                    dfs(G, v);
                }
            }

            // check that id[] gives strong components
            Debug.Assert(check(G));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges.
        /// A rooted out-tree is a DAG in which every vertex is reachable from a
        /// single vertex.
        /// The DAG returned is not chosen uniformly at random among all such DAGs.</summary>
        /// <param name="V">the number of vertices</param>
        /// <param name="E">the number of edges</param>
        /// <returns>a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges</returns>
        ///
        public static Digraph RootedOutDAG(int V, int E)
        {
            if (E > (long)V * (V - 1) / 2)
            {
                throw new ArgumentException("Too many edges");
            }
            if (E < V - 1)
            {
                throw new ArgumentException("Too few edges");
            }
            Digraph    G   = new Digraph(V);
            SET <Edge> set = new SET <Edge>();

            // fix a topological order
            int[] vertices = new int[V];
            for (int i = 0; i < V; i++)
            {
                vertices[i] = i;
            }
            StdRandom.Shuffle(vertices);

            // one edge pointing from each vertex, other than the root = vertices[V-1]
            for (int v = 0; v < V - 1; v++)
            {
                int  w = StdRandom.Uniform(v + 1, V);
                Edge e = new Edge(w, v);
                set.Add(e);
                G.AddEdge(vertices[w], vertices[v]);
            }

            while (G.E < E)
            {
                int  v = StdRandom.Uniform(V);
                int  w = StdRandom.Uniform(V);
                Edge e = new Edge(w, v);
                if ((v < w) && !set.Contains(e))
                {
                    set.Add(e);
                    G.AddEdge(vertices[w], vertices[v]);
                }
            }
            return(G);
        }
Ejemplo n.º 11
0
        private int count;     // number of strongly-connected components

        /// <summary>Computes the strong components of the digraph <c>G</c>.</summary>
        /// <param name="G">the digraph</param>
        ///
        public KosarajuSharirSCC(Digraph G)
        {
            // compute reverse postorder of reverse graph
            DepthFirstOrder dfs = new DepthFirstOrder(G.Reverse());

            // run DFS on G, using reverse postorder to guide calculation
            marked = new bool[G.V];
            id     = new int[G.V];
            foreach (int v in dfs.ReversePost())
            {
                if (!marked[v])
                {
                    this.dfs(G, v);
                    count++;
                }
            }
            // check that id[] gives strong components
            Debug.Assert(check(G));
        }
Ejemplo n.º 12
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);
        }
Ejemplo n.º 13
0
        // tournament
        /// <summary>
        /// Returns a random tournament digraph on <c>V</c> vertices. A tournament digraph
        /// is a DAG in which for every two vertices, there is one directed edge.
        /// A tournament is an oriented complete graph.</summary>
        /// <param name="V">the number of vertices</param>
        /// <returns>a random tournament digraph on <c>V</c> vertices</returns>
        ///
        public static Digraph Tournament(int V)
        {
            Digraph G = new Digraph(V);

            for (int v = 0; v < G.V; v++)
            {
                for (int w = v + 1; w < G.V; w++)
                {
                    if (StdRandom.Bernoulli(0.5))
                    {
                        G.AddEdge(v, w);
                    }
                    else
                    {
                        G.AddEdge(w, v);
                    }
                }
            }
            return(G);
        }
Ejemplo n.º 14
0
        public static void MainTest(string[] args)
        {
            string        filename  = args[0];
            string        delimiter = args[1];
            SymbolDigraph sg        = new SymbolDigraph(filename, delimiter);

            Digraph G = sg.G;
            string  t = Console.ReadLine();

            while (t != null)
            {
                if (sg.Contains(t))
                {
                    foreach (int v in G.Adj(sg.Index(t)))
                    {
                        Console.WriteLine("   " + sg.Name(v));
                    }
                }
                t = Console.ReadLine();
            }
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Initializes a new digraph that is a deep copy of the specified digraph.</summary>
 /// <param name="G">the digraph to copy</param>
 ///
 public Digraph(Digraph G) : this(G.V)
 {
     numEdges = G.E;
     for (int v = 0; v < V; v++)
     {
         this.indegree[v] = G.Indegree(v);
     }
     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);
         }
     }
 }
Ejemplo n.º 16
0
        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();
                }
            }
        }
Ejemplo n.º 17
0
        // BFS from single source
        private void bfs(Digraph G, int s)
        {
            LinkedQueue <int> q = new LinkedQueue <int>();

            marked[s] = true;
            distTo[s] = 0;
            q.Enqueue(s);
            while (!q.IsEmpty)
            {
                int v = q.Dequeue();
                foreach (int w in G.Adj(v))
                {
                    if (!marked[w])
                    {
                        edgeTo[w] = v;
                        distTo[w] = distTo[v] + 1;
                        marked[w] = true;
                        q.Enqueue(w);
                    }
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Computes the strong components of the digraph <c>G</c>.</summary>
        /// <param name="G">the digraph</param>
        ///
        public GabowSCC(Digraph G)
        {
            marked   = new bool[G.V];
            stack1   = new LinkedStack <int>();
            stack2   = new LinkedStack <int>();
            id       = new int[G.V];
            preorder = new int[G.V];
            for (int v = 0; v < G.V; v++)
            {
                id[v] = -1;
            }

            for (int v = 0; v < G.V; v++)
            {
                if (!marked[v])
                {
                    dfs(G, v);
                }
            }

            // check that id[] gives strong components
            Debug.Assert(check(G));
        }
Ejemplo n.º 19
0
        internal static void UnitTest(Digraph G, String description)
        {
            Console.WriteLine(description);
            Console.WriteLine("-------------------------------------");
            Console.Write(G);

            DirectedEulerianCycle euler = new DirectedEulerianCycle(G);

            Console.Write("Eulerian cycle: ");
            if (euler.HasEulerianCycle)
            {
                foreach (int v in euler.GetCycle())
                {
                    Console.Write(v + " ");
                }
                Console.WriteLine();
            }
            else
            {
                Console.WriteLine("none");
            }
            Console.WriteLine();
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Returns an Eulerian path digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the path</param>
        /// <param name="E">the number of edges in the path</param>
        /// <returns>a digraph that is a directed Eulerian path on <c>V</c> vertices</returns>
        ///        and <c>E</c> edges
        /// <exception cref="ArgumentException">if either V &lt;= 0 or E &lt; 0</exception>
        ///
        public static Digraph EulerianPath(int V, int E)
        {
            if (E < 0)
            {
                throw new ArgumentException("negative number of edges");
            }
            if (V <= 0)
            {
                throw new ArgumentException("An Eulerian path must have at least one vertex");
            }
            Digraph G = new Digraph(V);

            int[] vertices = new int[E + 1];
            for (int i = 0; i < E + 1; i++)
            {
                vertices[i] = StdRandom.Uniform(V);
            }
            for (int i = 0; i < E; i++)
            {
                G.AddEdge(vertices[i], vertices[i + 1]);
            }
            return(G);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Returns a random simple digraph on <c>V</c> vertices, with an
        /// edge between any two vertices with probability <c>p</c>. This is sometimes
        /// referred to as the Erdos-Renyi random digraph model.
        /// This implementations takes time propotional to V^2 (even if <c>p</c> is small).</summary>
        /// <param name="V">the number of vertices</param>
        /// <param name="p">the probability of choosing an edge</param>
        /// <returns>a random simple digraph on <c>V</c> vertices, with an edge between
        ///    any two vertices with probability <c>p</c></returns>
        /// <exception cref="ArgumentException">if probability is not between 0 and 1</exception>
        ///
        public static Digraph Simple(int V, double p)
        {
            if (p < 0.0 || p > 1.0)
            {
                throw new ArgumentException("Probability must be between 0 and 1");
            }
            Digraph G = new Digraph(V);

            for (int v = 0; v < V; v++)
            {
                for (int w = 0; w < V; w++)
                {
                    if (v != w)
                    {
                        if (StdRandom.Bernoulli(p))
                        {
                            G.AddEdge(v, w);
                        }
                    }
                }
            }
            return(G);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Returns an Eulerian cycle digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the cycle</param>
        /// <param name="E">the number of edges in the cycle</param>
        /// <returns>a digraph that is a directed Eulerian cycle on <c>V</c> vertices
        ///        and <c>E</c> edges</returns>
        /// <exception cref="ArgumentException">if either V &lt;= 0 or E &lt;= 0</exception>
        ///
        public static Digraph EulerianCycle(int V, int E)
        {
            if (E <= 0)
            {
                throw new ArgumentException("An Eulerian cycle must have at least one edge");
            }
            if (V <= 0)
            {
                throw new ArgumentException("An Eulerian cycle must have at least one vertex");
            }
            Digraph G = new Digraph(V);

            int[] vertices = new int[E];
            for (int i = 0; i < E; i++)
            {
                vertices[i] = StdRandom.Uniform(V);
            }
            for (int i = 0; i < E - 1; i++)
            {
                G.AddEdge(vertices[i], vertices[i + 1]);
            }
            G.AddEdge(vertices[E - 1], vertices[0]);
            return(G);
        }
Ejemplo n.º 23
0
        public static void MainTest(string[] args)
        {
            // read in digraph from command-line argument
            TextInput input = new TextInput(args[0]);
            Digraph   G     = new Digraph(input);

            DepthFirstOrder dfs = new DepthFirstOrder(G);

            Console.WriteLine("   v  pre post");
            Console.WriteLine("--------------");
            for (int v = 0; v < G.V; v++)
            {
                Console.Write("{0,4} {1,4:} {2,4}\n", v, dfs.Pre(v), dfs.Post(v));
            }

            Console.Write("Preorder:  ");
            foreach (int v in dfs.Pre())
            {
                Console.Write(v + " ");
            }
            Console.WriteLine();

            Console.Write("Postorder: ");
            foreach (int v in dfs.Post())
            {
                Console.Write(v + " ");
            }
            Console.WriteLine();

            Console.Write("Reverse postorder: ");
            foreach (int v in dfs.ReversePost())
            {
                Console.Write(v + " ");
            }
            Console.WriteLine();
        }
Ejemplo n.º 24
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));
        }
Ejemplo n.º 25
0
        public static void MainTest(string[] args)
        {
            int V = int.Parse(args[0]);
            int E = int.Parse(args[1]);

            // Eulerian cycle
            Digraph G1 = DigraphGenerator.EulerianCycle(V, E);

            DirectedEulerianCycle.UnitTest(G1, "Eulerian cycle");

            // Eulerian path
            Digraph G2 = DigraphGenerator.EulerianPath(V, E);

            DirectedEulerianCycle.UnitTest(G2, "Eulerian path");

            // empty digraph
            Digraph G3 = new Digraph(V);

            DirectedEulerianCycle.UnitTest(G3, "empty digraph");

            // self loop
            Digraph G4 = new Digraph(V);
            int     v4 = StdRandom.Uniform(V);

            G4.AddEdge(v4, v4);
            DirectedEulerianCycle.UnitTest(G4, "single self loop");

            // union of two disjoint cycles
            Digraph H1 = DigraphGenerator.EulerianCycle(V / 2, E / 2);
            Digraph H2 = DigraphGenerator.EulerianCycle(V - V / 2, E - E / 2);

            int[] perm = new int[V];
            for (int i = 0; i < V; i++)
            {
                perm[i] = i;
            }
            StdRandom.Shuffle(perm);
            Digraph G5 = new Digraph(V);

            for (int v = 0; v < H1.V; v++)
            {
                foreach (int w in H1.Adj(v))
                {
                    G5.AddEdge(perm[v], perm[w]);
                }
            }
            for (int v = 0; v < H2.V; v++)
            {
                foreach (int w in H2.Adj(v))
                {
                    G5.AddEdge(perm[V / 2 + v], perm[V / 2 + w]);
                }
            }
            DirectedEulerianCycle.UnitTest(G5, "Union of two disjoint cycles");

            // random digraph
            Digraph G6 = DigraphGenerator.Simple(V, E);

            DirectedEulerianCycle.UnitTest(G6, "simple digraph");

            // 4-vertex digraph - no data file
            //Digraph G7 = new Digraph(new TextInput("eulerianD.txt"));
            //DirectedEulerianCycle.UnitTest(G7, "4-vertex Eulerian digraph");
        }
Ejemplo n.º 26
0
        private int count;     // number of vertices reachable from s

        /// <summary>
        /// Computes the vertices in digraph <c>G</c> that are
        /// reachable from the source vertex <c>s</c>.</summary>
        /// <param name="G">the digraph</param>
        /// <param name="s">the source vertex</param>
        ///
        public DirectedDFS(Digraph G, int s)
        {
            marked = new bool[G.V];
            dfs(G, s);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Returns a random simple digraph on <c>V</c> vertices, <c>E</c>
        /// edges and (at least) <c>c</c> strong components. The vertices are randomly
        /// assigned integer labels between <c>0</c> and <c>c-1</c> (corresponding to
        /// strong components). Then, a strong component is creates among the vertices
        /// with the same label. Next, random edges (either between two vertices with
        /// the same labels or from a vetex with a smaller label to a vertex with a
        /// larger label). The number of components will be equal to the number of
        /// distinct labels that are assigned to vertices.</summary>
        /// <param name="V">the number of vertices</param>
        /// <param name="E">the number of edges</param>
        /// <param name="c">the (maximum) number of strong components</param>
        /// <returns>a random simple digraph on <c>V</c> vertices and
        /// <c>E</c> edges, with (at most) <c>c</c> strong components</returns>
        /// <exception cref="ArgumentException">if <c>c</c> is larger than <c>V</c></exception>
        ///
        public static Digraph Strong(int V, int E, int c)
        {
            if (c >= V || c <= 0)
            {
                throw new ArgumentException("Number of components must be between 1 and V");
            }
            if (E <= 2 * (V - c))
            {
                throw new ArgumentException("Number of edges must be at least 2(V-c)");
            }
            if (E > (long)V * (V - 1) / 2)
            {
                throw new ArgumentException("Too many edges");
            }

            // the digraph
            Digraph G = new Digraph(V);

            // edges added to G (to avoid duplicate edges)
            SET <Edge> set = new SET <Edge>();

            int[] label = new int[V];
            for (int v = 0; v < V; v++)
            {
                label[v] = StdRandom.Uniform(c);
            }

            // make all vertices with label c a strong component by
            // combining a rooted in-tree and a rooted out-tree
            for (int i = 0; i < c; i++)
            {
                // how many vertices in component c
                int count = 0;
                for (int v = 0; v < G.V; v++)
                {
                    if (label[v] == i)
                    {
                        count++;
                    }
                }

                // if (count == 0) System.err.println("less than desired number of strong components");

                int[] vertices = new int[count];
                int   j        = 0;
                for (int v = 0; v < V; v++)
                {
                    if (label[v] == i)
                    {
                        vertices[j++] = v;
                    }
                }
                StdRandom.Shuffle(vertices);

                // rooted-in tree with root = vertices[count-1]
                for (int v = 0; v < count - 1; v++)
                {
                    int  w = StdRandom.Uniform(v + 1, count);
                    Edge e = new Edge(w, v);
                    set.Add(e);
                    G.AddEdge(vertices[w], vertices[v]);
                }

                // rooted-out tree with root = vertices[count-1]
                for (int v = 0; v < count - 1; v++)
                {
                    int  w = StdRandom.Uniform(v + 1, count);
                    Edge e = new Edge(v, w);
                    set.Add(e);
                    G.AddEdge(vertices[v], vertices[w]);
                }
            }

            while (G.E < E)
            {
                int  v = StdRandom.Uniform(V);
                int  w = StdRandom.Uniform(V);
                Edge e = new Edge(v, w);
                if (!set.Contains(e) && v != w && label[v] <= label[w])
                {
                    set.Add(e);
                    G.AddEdge(v, w);
                }
            }

            return(G);
        }
Ejemplo n.º 28
0
        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());
        }