Exemple #1
0
        /// <summary>
        /// check that algorithm computes either the topological order or finds a directed cycle
        /// </summary>
        /// <param name="g"></param>
        /// <param name="v"></param>
        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;
                }

                //found new vertex, so recur
                if (!_marked[w])
                {
                    _edgeTo[w] = v;
                    Dfs(g, w);
                }

                // trace back directed cycle
                else if (_onStack[w])
                {
                    _cycle = new Collections.Stack <Integer>();
                    for (var x = v; x != w; x = _edgeTo[x])
                    {
                        _cycle.Push(x);
                    }
                    _cycle.Push(w);
                    _cycle.Push(v);
                    //assert check();
                }
            }
            _onStack[v] = false;
        }
Exemple #2
0
        /// <summary>
        /// BFS from multiple sources
        /// </summary>
        /// <param name="g"></param>
        /// <param name="sources"></param>
        private void Bfs(Digraph g, IEnumerable <Integer> sources)
        {
            var q = new Collections.Queue <Integer>();

            foreach (int s in sources)
            {
                _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);
                    }
                }
            }
        }
Exemple #3
0
        private void Dfs(Digraph g, int v)
        {
            _marked[v] = true;
            _low[v]    = _pre++;
            var min = _low[v];

            _stack.Push(v);
            foreach (int j in g.Adj(v))
            {
                if (!_marked[j])
                {
                    Dfs(g, j);
                }
                if (_low[j] < min)
                {
                    min = _low[j];
                }
            }
            if (min < _low[v])
            {
                _low[v] = min;
                return;
            }
            int w;

            do
            {
                w       = _stack.Pop();
                _id[w]  = _count;
                _low[w] = g.V;
            } while (w != v);
            _count++;
        }
Exemple #4
0
        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++;
            }
        }
Exemple #5
0
 private void Dfs(Digraph g, int v)
 {
     _count++;
     _marked[v] = true;
     foreach (int w in g.Adj(v))
     {
         if (!_marked[w]) Dfs(g, w);
     }
 }
Exemple #6
0
        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 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);
        }
Exemple #8
0
        /// <summary>
        /// certify that digraph is acyclic
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool Check(Digraph g)
        {
            // digraph is acyclic
            if (HasOrder())
            {
                // check that ranks are a permutation of 0 to V-1
                var found = new bool[g.V];
                for (var i = 0; i < g.V; i++)
                {
                    found[Rank(i)] = true;
                }
                for (var i = 0; i < g.V; i++)
                {
                    if (!found[i])
                    {
                        Console.Error.WriteLine($"No vertex with rank {i}");
                        return(false);
                    }
                }

                // check that ranks provide a valid topological order
                for (var v = 0; v < g.V; v++)
                {
                    foreach (int w in g.Adj(v))
                    {
                        if (Rank(v) > Rank(w))
                        {
                            Console.WriteLine($"{v}-{w}: rank({v}) = {Rank(v)}, rank({w}) = {Rank(w)}{Environment.NewLine}");
                            return(false);
                        }
                    }
                }

                // check that order() is consistent with rank()
                var r = 0;
                foreach (int v in Order())
                {
                    if (Rank(v) != r)
                    {
                        Console.WriteLine("order() and rank() inconsistent");
                        return(false);
                    }
                    r++;
                }
            }


            return(true);
        }
Exemple #9
0
        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);
        }
Exemple #10
0
 /// <summary>
 /// run DFS in digraph G from vertex v and compute preorder/postorder
 /// </summary>
 /// <param name="g"></param>
 /// <param name="v"></param>
 private void Dfs(Digraph g, int v)
 {
     _marked[v] = true;
     _pre[v]    = _preCounter++;
     _preorder.Enqueue(v);
     foreach (int w in g.Adj(v))
     {
         if (!_marked[w])
         {
             Dfs(g, w);
         }
     }
     _postorder.Enqueue(v);
     _post[v] = _postCounter++;
 }
Exemple #11
0
        /// <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);
        }
Exemple #12
0
        /// <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);
        }
Exemple #13
0
        private readonly bool[] _marked;  // marked[v] = is there an s->v path?

        /// <summary>
        /// Computes the vertices reachable from the source vertex <tt>s</tt> in the digraph <tt>G</tt>.
        /// </summary>
        /// <param name="g">g the digraph</param>
        /// <param name="s">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
            var adj = new IEnumerator <Integer> [g.V];

            for (var v = 0; v < g.V; v++)
            {
                adj[v] = g.Adj(v).GetEnumerator();
            }

            // depth-first search using an explicit stack
            var stack = new Collections.Stack <Integer>();

            _marked[s] = true;
            stack.Push(s);
            while (!stack.IsEmpty())
            {
                int v = stack.Peek();
                if (adj[v].MoveNext())
                {
                    int w = adj[v].Current;
                    // StdOut.printf("check %d\n", w);
                    if (!_marked[w])
                    {
                        // discovered vertex w for the first time
                        _marked[w] = true;
                        // edgeTo[w] = v;
                        stack.Push(w);
                        // StdOut.printf("dfs(%d)\n", w);
                    }
                }
                else
                {
                    // StdOut.printf("%d done\n", v);
                    stack.Pop();
                }
            }
        }
        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);
        }
        private readonly bool[] _marked; // marked[v] = is there an s->v path?

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Computes the vertices reachable from the source vertex <tt>s</tt> in the digraph <tt>G</tt>.
        /// </summary>
        /// <param name="g">g the digraph</param>
        /// <param name="s">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
            var adj = new IEnumerator<Integer>[g.V];
            for (var v = 0; v < g.V; v++)
                adj[v] = g.Adj(v).GetEnumerator();

            // depth-first search using an explicit stack
            var stack = new Collections.Stack<Integer>();
            _marked[s] = true;
            stack.Push(s);
            while (!stack.IsEmpty())
            {
                int v = stack.Peek();
                if (adj[v].MoveNext())
                {
                    int w = adj[v].Current;
                    // StdOut.printf("check %d\n", w);
                    if (!_marked[w])
                    {
                        // discovered vertex w for the first time
                        _marked[w] = true;
                        // edgeTo[w] = v;
                        stack.Push(w);
                        // StdOut.printf("dfs(%d)\n", w);
                    }
                }
                else
                {
                    // StdOut.printf("%d done\n", v);
                    stack.Pop();
                }
            }
        }
 /// <summary>
 /// BFS from multiple sources
 /// </summary>
 /// <param name="g"></param>
 /// <param name="sources"></param>
 private void Bfs(Digraph g, IEnumerable<Integer> sources)
 {
     var q = new Collections.Queue<Integer>();
     foreach (int s in sources)
     {
         _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);
             }
         }
     }
 }
        /// <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;
        }
Exemple #18
0
        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);
        }
Exemple #19
0
        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++;
            }
        }
Exemple #20
0
 private void Dfs(Digraph g, int v)
 {
     _count++;
     _marked[v] = true;
     foreach (int w in g.Adj(v))
     {
         if (!_marked[w]) Dfs(g, w);
     }
 }
        /// <summary>
        /// check that algorithm computes either the topological order or finds a directed cycle
        /// </summary>
        /// <param name="g"></param>
        /// <param name="v"></param>
        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;

                //found new vertex, so recur
                if (!_marked[w])
                {
                    _edgeTo[w] = v;
                    Dfs(g, w);
                }

                // trace back directed cycle
                else if (_onStack[w])
                {
                    _cycle = new Collections.Stack<Integer>();
                    for (var x = v; x != w; x = _edgeTo[x])
                    {
                        _cycle.Push(x);
                    }
                    _cycle.Push(w);
                    _cycle.Push(v);
                    //assert check();
                }
            }
            _onStack[v] = false;
        }
        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();
        }
Exemple #23
0
 private void Dfs(Digraph g, int v)
 {
     _marked[v] = true;
     _low[v] = _pre++;
     var min = _low[v];
     _stack.Push(v);
     foreach (int j in g.Adj(v))
     {
         if (!_marked[j]) Dfs(g, j);
         if (_low[j] < min) min = _low[j];
     }
     if (min < _low[v])
     {
         _low[v] = min;
         return;
     }
     int w;
     do
     {
         w = _stack.Pop();
         _id[w] = _count;
         _low[w] = g.V;
     } while (w != v);
     _count++;
 }
        /// <summary>
        /// certify that digraph is acyclic
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool Check(Digraph g)
        {
            // digraph is acyclic
            if (HasOrder())
            {
                // check that ranks are a permutation of 0 to V-1
                var found = new bool[g.V];
                for (var i = 0; i < g.V; i++)
                {
                    found[Rank(i)] = true;
                }
                for (var i = 0; i < g.V; i++)
                {
                    if (!found[i])
                    {
                        Console.Error.WriteLine($"No vertex with rank {i}");
                        return false;
                    }
                }

                // check that ranks provide a valid topological order
                for (var v = 0; v < g.V; v++)
                {
                    foreach (int w in g.Adj(v))
                    {
                        if (Rank(v) > Rank(w))
                        {
                            Console.WriteLine($"{v}-{w}: rank({v}) = {Rank(v)}, rank({w}) = {Rank(w)}{Environment.NewLine}");
                            return false;
                        }
                    }
                }

                // check that order() is consistent with rank()
                var r = 0;
                foreach (int v in Order())
                {
                    if (Rank(v) != r)
                    {
                        Console.WriteLine("order() and rank() inconsistent");
                        return false;
                    }
                    r++;
                }
            }

            return true;
        }
 /// <summary>
 /// run DFS in digraph G from vertex v and compute preorder/postorder
 /// </summary>
 /// <param name="g"></param>
 /// <param name="v"></param>
 private void Dfs(Digraph g, int v)
 {
     _marked[v] = true;
     _pre[v] = _preCounter++;
     _preorder.Enqueue(v);
     foreach (int w in g.Adj(v))
     {
         if (!_marked[w])
         {
             Dfs(g, w);
         }
     }
     _postorder.Enqueue(v);
     _post[v] = _postCounter++;
 }
Exemple #26
0
        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();
        }