• prim算法(解决修路问题)


    prim算法(解决修路问题)

    定义:

    普利姆(Prim)算法求最小生成树,也就是在包含 n 个顶点的连通图中,找出只有(n-1)条边包含所有 n 个顶点的连通子图,也就是所谓的极小连通子图

    关于最小生成树:

    修路问题本质就是就是最小生成树问题, 先介绍一下最小生成树(Minimum Cost Spanning Tree),简称 MST。给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树

    1)   N 个顶点,一定有 N-1 条边

    2)   包含全部顶点

    3)   N-1 条边都在图中

    4)   举例说明(如图:)

    5)   求最小生成树的算法主要是普里姆算法和克鲁斯卡尔算法

    问题:

     思路分析:

     代码实现

    package com.edu.algorithm.普利姆算法;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * <p>prim算法解决修路问题</p>
     *
     * @作者 five-five
     * @创建时间 2020/9/2
     */
    public class 修路问题 {
        private static List<Character> characters = new ArrayList<>();
        public static void main(String[] args) {
            char[] chars = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};//表示顶点
            //只要权重不是不是Integer.MAX_VALUE,就说明个顶点连接的,而且数字表示两条路权重
            int[][] weight = new int[][]{
                    //a                b c     d              e                 f                g
                    {Integer.MAX_VALUE, 5, 7, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 2},//a
                    {5, Integer.MAX_VALUE, Integer.MAX_VALUE, 9, Integer.MAX_VALUE, Integer.MAX_VALUE, 3},//b
                    {7, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 8, Integer.MAX_VALUE, Integer.MAX_VALUE},//c
                    {Integer.MAX_VALUE, 9, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 4, Integer.MAX_VALUE},//d
                    {Integer.MAX_VALUE, Integer.MAX_VALUE, 8, Integer.MAX_VALUE, Integer.MAX_VALUE, 5, 4},//e
                    {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 4, 5, Integer.MAX_VALUE, 6},//f
                    {2, 3, Integer.MAX_VALUE, Integer.MAX_VALUE, 4, 6, Integer.MAX_VALUE},};//g
            prim(weight, chars);
            System.out.println(characters);
        }
    
        private static void prim(int[][] weight, char[] chars) {
            prim(weight, chars, 0);
        }
    
        /**
         * @param weight
         * @param chars
         * @param start  从那个地方开始
         * @return
         */
        private static void prim(int[][] weight, char[] chars, int start) {
            //记录访问过的顶点
            int[] visited = new int[chars.length];
            //把当前节点记录为访问过
            visited[start] = 1;//1为访问过,0为未访问过
            int minweight = Integer.MAX_VALUE;
            int h1 = 0;
            int h2 = 0;
            //边数为顶点数-1
            for (int i = 0; i < chars.length - 1; i++) {
                //这个是确定每一次生成的子图 ,和哪个结点的距离最近
                for (int j = 0; j < weight.length; j++) {
                    for (int k = 0; k < weight[j].length; k++) {
                        //寻找已经访问过的结点和未访问过的结点间的权值最小的边
                        if (visited[j] == 1 && visited[k] == 0 && minweight > weight[j][k]) {
                            minweight = weight[j][k];
                            h1 = j;
                            h2 = k;
                        }
                    }
                }
                System.out.println("边<"+chars[h1]+","+chars[h2]+"> 权值"+minweight);
                characters.add(chars[h1]);
                //开始标记记录的minweight的坐标
                visited[h2] = 1;
                minweight = Integer.MAX_VALUE;
            }
        }
    }

    数组说明:因为每次迭代都是寻找已经访问过的结点和未访问过的结点间的权值最小的边。

    如图:

  • 相关阅读:
    ThinkPHP3.2.3使用分页
    使用phpmailer发送邮件
    字体笔记
    jquery实现上传文件大小类型的验证
    两个矩阵中的dp题的差异
    Linux进程间通信——使用共享内存
    使用管道完成进程间通信(匿名管道pipe、命名管道fifo)
    为什么 C++ 有指针了还要引用?
    实现一个Memcpy函数
    猜帽子颜色问题
  • 原文地址:https://www.cnblogs.com/five-five/p/13601573.html
Copyright © 2020-2023  润新知