예제 #1
0
        private LinkedQueue <Edge> mst = new LinkedQueue <Edge>(); // edges in MST

        /// <summary>
        /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.</summary>
        /// <param name="G">the edge-weighted graph</param>
        ///
        public KruskalMST(EdgeWeightedGraph G)
        {
            // more efficient to build heap by passing array of edges
            MinPQ <Edge> pq = new MinPQ <Edge>();

            foreach (Edge e in G.Edges())
            {
                pq.Insert(e);
            }

            // run greedy algorithm
            UF uf = new UF(G.V);

            while (!pq.IsEmpty && mst.Count < G.V - 1)
            {
                Edge e = pq.DelMin();
                int  v = e.Either;
                int  w = e.Other(v);
                if (!uf.Connected(v, w))
                {                   // v-w does not create a cycle
                    uf.Union(v, w); // merge v and w components
                    mst.Enqueue(e); // add edge e to mst
                    weight += e.Weight;
                }
            }

            // check optimality conditions
            Debug.Assert(check(G));
        }
예제 #2
0
        private double weight;                     // weight of MST

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

            // repeat at most log V times or until we have V-1 edges
            for (int t = 1; t < G.V && mst.Count < 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()
                Edge[] closest = new Edge[G.V];
                foreach (Edge 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 (int i = 0; i < G.V; i++)
                {
                    Edge 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
            Debug.Assert(check(G));
        }
예제 #3
0
파일: UF.cs 프로젝트: zzhi/Algs4Net
        public static void MainTest(string[] args)
        {
            TextInput StdIn = new TextInput();
            int       N     = StdIn.ReadInt();
            UF        uf    = new UF(N);

            while (!StdIn.IsEmpty)
            {
                int p = StdIn.ReadInt();
                int q = StdIn.ReadInt();
                if (uf.Connected(p, q))
                {
                    continue;
                }
                uf.Union(p, q);
                Console.WriteLine(p + " " + q);
            }
            Console.WriteLine(uf.Count + " components");
        }
예제 #4
0
        // check optimality conditions (takes time proportional to E V lg* V)
        private bool check(EdgeWeightedGraph G)
        {
            // check total weight
            double total = 0.0;

            foreach (Edge e in Edges())
            {
                total += e.Weight;
            }
            if (Math.Abs(total - Weight) > FLOATING_POINT_EPSILON)
            {
                Console.Error.Write("Weight of edges does not equal Weight: {0} vs. {0}\n", total, Weight);
                return(false);
            }

            // check that it is acyclic
            UF uf = new UF(G.V);

            foreach (Edge e in Edges())
            {
                int v = e.Either, w = e.Other(v);
                if (uf.Connected(v, w))
                {
                    Console.Error.WriteLine("Not a forest");
                    return(false);
                }
                uf.Union(v, w);
            }

            // check that it is a spanning forest
            foreach (Edge e in G.Edges())
            {
                int v = e.Either, w = e.Other(v);
                if (!uf.Connected(v, w))
                {
                    Console.Error.WriteLine("Not a spanning forest");
                    return(false);
                }
            }

            // check that it is a minimal spanning forest (cut optimality conditions)
            foreach (Edge e in Edges())
            {
                // all edges in MST except e
                uf = new UF(G.V);
                foreach (Edge f in mst)
                {
                    int x = f.Either, y = f.Other(x);
                    if (f != e)
                    {
                        uf.Union(x, y);
                    }
                }

                // check that e is min weight edge in crossing cut
                foreach (Edge f in G.Edges())
                {
                    int x = f.Either, y = f.Other(x);
                    if (!uf.Connected(x, y))
                    {
                        if (f.Weight < e.Weight)
                        {
                            Console.Error.WriteLine("Edge " + f + " violates cut optimality conditions");
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }