zoukankan      html  css  js  c++  java
  • Prim算法

    1、算法简单描述

    1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

    2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

    3).重复下列操作,直到Vnew = V:

    a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

    b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;

    4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。

    public class PrimMST {
        private static final double FLOATING_POINT_EPSILON = 1E-12;
    
        private Edge[] edgeTo;        // edgeTo[v] = shortest edge from tree vertex to non-tree vertex
        private double[] distTo;      // distTo[v] = weight of shortest such edge
        private boolean[] marked;     // marked[v] = true if v on tree, false otherwise
        private IndexMinPQ<Double> pq;
    
        /**
         * Compute a minimum spanning tree (or forest) of an edge-weighted graph.
         * @param G the edge-weighted graph
         */
        public PrimMST(EdgeWeightedGraph G) {
            edgeTo = new Edge[G.V()];
            distTo = new double[G.V()];
            marked = new boolean[G.V()];
            pq = new IndexMinPQ<Double>(G.V());
            for (int v = 0; v < G.V(); v++)
                distTo[v] = Double.POSITIVE_INFINITY;
    
            for (int v = 0; v < G.V(); v++)      // run from each vertex to find
                if (!marked[v]) prim(G, v);      // minimum spanning forest
    
            // check optimality conditions
            assert check(G);
        }
    
        // run Prim's algorithm in graph G, starting from vertex s
        private void prim(EdgeWeightedGraph G, int s) {
            distTo[s] = 0.0;
            pq.insert(s, distTo[s]);
            while (!pq.isEmpty()) {
                int v = pq.delMin();
                scan(G, v);
            }
        }
    
        // scan vertex v
        private void scan(EdgeWeightedGraph G, int v) {
            marked[v] = true;
            for (Edge e : G.adj(v)) {
                int w = e.other(v);
                if (marked[w]) continue;         // v-w is obsolete edge
                if (e.weight() < distTo[w]) {
                    distTo[w] = e.weight();
                    edgeTo[w] = e;
                    if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);
                    else                pq.insert(w, distTo[w]);
                }
            }
        }
    
        /**
         * Returns the edges in a minimum spanning tree (or forest).
         * @return the edges in a minimum spanning tree (or forest) as
         *    an iterable of edges
         */
        public Iterable<Edge> edges() {
            Queue<Edge> mst = new Queue<Edge>();
            for (int v = 0; v < edgeTo.length; v++) {
                Edge e = edgeTo[v];
                if (e != null) {
                    mst.enqueue(e);
                }
            }
            return mst;
        }
    
        /**
         * Returns the sum of the edge weights in a minimum spanning tree (or forest).
         * @return the sum of the edge weights in a minimum spanning tree (or forest)
         */
        public double weight() {
            double weight = 0.0;
            for (Edge e : edges())
                weight += e.weight();
            return weight;
        }
    
    
        // check optimality conditions (takes time proportional to E V lg* V)
        private boolean check(EdgeWeightedGraph G) {
    
            // check weight
            double totalWeight = 0.0;
            for (Edge e : edges()) {
                totalWeight += e.weight();
            }
            if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {
                System.err.printf("Weight of edges does not equal weight(): %f vs. %f
    ", totalWeight, weight());
                return false;
            }
    
            // check that it is acyclic
            UF uf = new UF(G.V());
            for (Edge e : edges()) {
                int v = e.either(), w = e.other(v);
                if (uf.find(v) == uf.find(w)) {
                    System.err.println("Not a forest");
                    return false;
                }
                uf.union(v, w);
            }
    
            // check that it is a spanning forest
            for (Edge e : G.edges()) {
                int v = e.either(), w = e.other(v);
                if (uf.find(v) != uf.find(w)) {
                    System.err.println("Not a spanning forest");
                    return false;
                }
            }
    
            // check that it is a minimal spanning forest (cut optimality conditions)
            for (Edge e : edges()) {
    
                // all edges in MST except e
                uf = new UF(G.V());
                for (Edge f : edges()) {
                    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
                for (Edge f : G.edges()) {
                    int x = f.either(), y = f.other(x);
                    if (uf.find(x) != uf.find(y)) {
                        if (f.weight() < e.weight()) {
                            System.err.println("Edge " + f + " violates cut optimality conditions");
                            return false;
                        }
                    }
                }
    
            }
    
            return true;
        }
    
        /**
         * Unit tests the {@code PrimMST} data type.
         *
         * @param args the command-line arguments
         */
        public static void main(String[] args) {
            In in = new In(args[0]);
            EdgeWeightedGraph G = new EdgeWeightedGraph(in);
            PrimMST mst = new PrimMST(G);
            for (Edge e : mst.edges()) {
                StdOut.println(e);
            }
            StdOut.printf("%.5f
    ", mst.weight());
        }
    
    
    }
  • 相关阅读:
    C程序设计语言阅读笔记
    Leetcode: . 存在重复元素 III
    Leetcode : 存在重复元素 II
    Leetcode : 二叉搜索树结点最小距离
    Leetcode: 二叉树的最大深度
    Leetcode: 二叉树的最小深度
    精益创业 埃里克莱斯 读书笔记总结--2020年的第12/100本
    经营最重要的事 梅纳德韦伯 读书笔记总结--2020年的第11/100本
    《创业36条军规 孙陶然》精读 读书笔记总结----《创业必读书第5本》---建立认知:有哪些优秀的创业经验 第3本
    原则 瑞达利欧 读书笔记总结--2020年的第9/100本
  • 原文地址:https://www.cnblogs.com/hequnwang/p/14331110.html
Copyright © 2011-2022 走看看