最小生成树——Prim算法

目录

基本思想

实现

伪代码

实际问题求解


最小生成树:带权连通图的生成树中 边的权值之和最小的那个生成树。

  • 最小生成树不是唯一的。当图中的各边权值互不相等时,最小生成树是唯一的;
  • 若无向连通图本身是一棵树时(边数比顶点数少1 ),则最小生成树就是它本身。
  • 最小生成树的边数为顶点数减1

基本思想

(找距离最近的结点)

  1. 任选一个结点v1,然后选择离【当前选中结点集合】最近的一个结点v2;
  2. 再选择离【当前选中结点集合{v1,v2}】结点最近的一个结点;依次重复,直到点全部被选中。

  • Prim算法的时间复杂度为O(|V|^2)不依赖于|E|,因此它适用于求解边稠密图的最小生成树。

实现

伪代码

void Prim (G , T ) { 
    T = 空集 ; 				//初始化空树
    U={w}; 					//添加任一顶点w
    while( (V-U) != 空集 ) {	//若树中不含全部顶点
       设 ( u , v ) 是使u∈U 与 v∈(V-U),且权值最小的边;
        T=TU{ (u,v) };		//边归入树
        U=U U{v);			//顶点归入树
     }
}

实际问题求解

 [USACO3.1]最短网络 Agri-Net

题目背景:Farmer John 被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。

题目描述:FJ 已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。

你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过10^5

(采用基本Prim算法求解:Kruskal算法求解见专栏)

public class MST {
    public int prim(int[][] w){
        int n=w.length;
        //最小生成树总权值
        int result=0;
        //加入的顶点集
        boolean[] Vex=new boolean[n];
        //当前已确定的顶点集到i的最短距离
        int[] dis=new int[n];
    
        //初始化
        //任选v点开始点
        int v=0;
        Vex[0]=true;
        for (int i = 0; i < n; i++) {
            dis[i]=w[v][i];
        }
    
        //遍历n次,选n个顶点
        for (int l = 0; l < n; l++) {
            //选取当前顶点集到其它顶点的最短路径
            int temp=-1;
            for (int i = 0; i < n; i++) {
                if ((!Vex[i])&&(temp==-1||(dis[i]>0&&dis[i]<dis[temp]))){
                    temp=i;
                }
            }
            if (temp==-1) {
                return -1;
            }
            //将找到的距离最近的顶点加入顶点集
            Vex[temp] = true;
            v = temp;
            result += dis[temp];
    
            //由于顶点集新加入一个顶点,要更新当前已确定的顶点集到i的最短距离
            for (int i = 0; i < w.length; i++) {
                if ((!Vex[i])&&w[v][i]>0&&w[v][i]<dis[i]){
                    dis[i]=w[v][i];
                }
            }
        }
        return result;
    }
    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
        int[][] w=new int[n][n];
        for (int i = 0; i < w.length; i++) {
            for (int j = 0; j < w.length; j++) {
                w[i][j]=scan.nextInt();
            }
        }
        System.out.println(new MST().prim(w));
    }
}
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SS上善

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值