Ejemplo n.º 1
0
        /// <summary>
        /// Adds the undirected edge <tt>e</tt> to this edge-weighted graph.
        /// </summary>
        /// <param name="e">e the edge</param>
        /// <exception cref="IndexOutOfRangeException">unless both endpoints are between 0 and V-1</exception>
        public void AddEdge(EdgeW e)
        {
            var v = e.Either();
            var w = e.Other(v);

            ValidateVertex(v);
            ValidateVertex(w);
            _adj[v].Add(e);
            _adj[w].Add(e);
            E++;
        }
Ejemplo n.º 2
0
        private readonly double _weight;                       // weight of MST

        /// <summary>
        /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.
        /// </summary>
        /// <param name="g">g the edge-weighted graph</param>
        public BoruvkaMST(EdgeWeightedGraph g)
        {
            var uf = new UF(g.V);

            // repeat at most log V times or until we have V-1 edges
            for (var t = 1; t < g.V && _mst.Size() < g.V - 1; t = t + t)
            {
                // foreach tree in forest, find closest edge
                // if edge weights are equal, ties are broken in favor of first edge in G.edges()
                var closest = new EdgeW[g.V];
                foreach (var e in g.Edges())
                {
                    int v = e.Either(), w = e.Other(v);
                    int i = uf.Find(v), j = uf.Find(w);
                    if (i == j)
                    {
                        continue;           // same tree
                    }
                    if (closest[i] == null || Less(e, closest[i]))
                    {
                        closest[i] = e;
                    }
                    if (closest[j] == null || Less(e, closest[j]))
                    {
                        closest[j] = e;
                    }
                }

                // add newly discovered edges to MST
                for (var i = 0; i < g.V; i++)
                {
                    var e = closest[i];
                    if (e != null)
                    {
                        int v = e.Either(), w = e.Other(v);
                        // don't add the same edge twice
                        if (!uf.Connected(v, w))
                        {
                            _mst.Add(e);
                            _weight += e.Weight;
                            uf.Union(v, w);
                        }
                    }
                }
            }

            // check optimality conditions
            //assert check(G);
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Initializes a random edge-weighted graph with <tt>V</tt> vertices and <em>E</em> edges.
 /// </summary>
 /// <param name="v">V the number of vertices</param>
 /// <param name="e">E the number of edges</param>
 /// <exception cref="ArgumentException">if <tt>V</tt> &lt; 0</exception>
 /// <exception cref="ArgumentException">if <tt>E</tt> &lt; 0</exception>
 public EdgeWeightedGraph(int v, int e) : this(v)
 {
     if (e < 0)
     {
         throw new ArgumentException("Number of edges must be nonnegative");
     }
     for (var i = 0; i < e; i++)
     {
         var ve     = StdRandom.Uniform(v);
         var we     = StdRandom.Uniform(v);
         var weight = Math.Round(100 * StdRandom.Uniform()) / 100.0;
         var edge   = new EdgeW(ve, we, weight);
         AddEdge(edge);
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// relax edge e and update pq if changed
        /// </summary>
        /// <param name="e"></param>
        /// <param name="v"></param>
        private void Relax(EdgeW e, int v)
        {
            var w = e.Other(v);

            if (_distTo[w] > _distTo[v] + e.Weight)
            {
                _distTo[w] = _distTo[v] + e.Weight;
                _edgeTo[w] = e;
                if (_pq.Contains(w))
                {
                    _pq.DecreaseKey(w, _distTo[w]);
                }
                else
                {
                    _pq.Insert(w, _distTo[w]);
                }
            }
        }
Ejemplo n.º 5
0
        private readonly Collections.Stack <Integer> _cycle = new Collections.Stack <Integer>();  // Eulerian cycle; null if no such cycle


        /// <summary>
        /// Computes an Eulerian cycle in the specified graph, if one exists.
        /// </summary>
        /// <param name="g">g the graph</param>
        public EulerianCycle(Graph g)
        {
            // must have at least one EdgeW
            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 (var 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 EdgeW data type is used to avoid exploring both copies of an EdgeW v-w
            var adj = new Collections.Queue <EdgeW> [g.V];

            for (var v = 0; v < g.V; v++)
            {
                adj[v] = new Collections.Queue <EdgeW>();
            }

            for (var v = 0; v < g.V; v++)
            {
                var selfLoops = 0;
                foreach (int w in g.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            var e = new EdgeW(v, w, 0);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        var e = new EdgeW(v, w, 0);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize Collections.Stack with any non-isolated vertex
            var s     = NonIsolatedVertex(g);
            var stack = new Collections.Stack <Integer>();

            stack.Push(s);

            // greedily search through EdgeWs in iterative DFS style
            _cycle = new Collections.Stack <Integer>();
            while (!stack.IsEmpty())
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty())
                {
                    var edgeW = adj[v].Dequeue();
                    if (edgeW.IsUsed)
                    {
                        continue;
                    }
                    edgeW.IsUsed = true;
                    stack.Push(v);
                    v = edgeW.Other(v);
                }
                // push vertex with no more leaving EdgeWs to cycle
                _cycle.Push(v);
            }

            // check if all EdgeWs are used
            if (_cycle.Size() != g.E + 1)
            {
                _cycle = null;
            }

            //assert certifySolution(G);
        }
Ejemplo n.º 6
0
        private readonly Collections.Stack <Integer> _path;   // Eulerian path; null if no suh path


        /// <summary>
        /// Computes an Eulerian path in the specified graph, if one exists.
        /// </summary>
        /// <param name="g">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
            var oddDegreeVertices = 0;
            var s = NonIsolatedVertex(g);

            for (var 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
            var adj = new Collections.Queue <EdgeW> [g.V];

            for (var v = 0; v < g.V; v++)
            {
                adj[v] = new Collections.Queue <EdgeW>();
            }

            for (var v = 0; v < g.V; v++)
            {
                var selfLoops = 0;
                foreach (int w in g.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            var e = new EdgeW(v, w, 0);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        var e = new EdgeW(v, w, 0);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize stack with any non-isolated vertex
            var stack = new Collections.Stack <Integer>();

            stack.Push(s);

            // greedily search through edges in iterative DFS style
            _path = new Collections.Stack <Integer>();
            while (!stack.IsEmpty())
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty())
                {
                    var 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.Size() != g.E + 1)
            {
                _path = null;
            }

            //assert certifySolution(G);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// is the weight of edge e strictly less than that of edge f?
 /// </summary>
 /// <param name="e"></param>
 /// <param name="f"></param>
 /// <returns></returns>
 private static bool Less(EdgeW e, EdgeW f)
 {
     return(e.Weight < f.Weight);
 }