【期末算法课程设计十道题】-【最小生成树】-【5-修路计算成本】

大家好,我是被白菜拱的猪。

一个热爱学习废寝忘食头悬梁锥刺股,痴迷于girl的潇洒从容淡然coding handsome boy!

第五题

在这里插入图片描述

这题就是单纯的求最小生成树,然后求其权值和。
最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。
没什么好说的,代码我也是网上找的,现阶段我还没有独自写出这些代码,哎呀,算法一定要好好学。
不过话说,学校是真得穷啊,这个修那个修,想想当时来大学那会,就跟个施工现场似的,出题人也是结合是现实啊哈哈哈。

no 代码 you say 个 jb。

/**
 * 
 */


import java.util.ArrayList;
import java.util.Collections;
/**  
* @ClassName: Demo5  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Lily  
* @date 2020年6月17日    
*/
import java.util.Scanner;

class Edge{
    int v; //边的权值
    int[] ConnectPoint = new int[2];  //边所连接的点
    int isSelect; //是否被选择,1表示被选,0表示没有被选
    char No; //图的编号,a,b,c,d...在创建图的时候初始化的
}

public class Main {
	
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int m=scan.nextInt();
		int[][] map=new int[m][3];       
		  for(int i=0;i<m;i++)
		  {
			  for(int j=0;j<3;j++){
				  map[i][j]=scan.nextInt();
			  }
		    }
		  for(int i=0;i<m;i++)
		  {
			  for(int j=0;j<2;j++){
				  map[i][j]=map[i][j]-1;
			  }
		    }
		 

        int[][] mstEdges = kruskal(n, map);

        int totalCost = 0;
        //输出构树的边集
        for (int i = 0; i < mstEdges.length; i++) {
            int[] edge = mstEdges[i];
            totalCost += edge[2];
        }

        System.out.println(totalCost);
    }

    public static int[][] kruskal(int n, int[][] edges) {
        /**
         * @Description: 克鲁斯卡尔算法求最小生成树
         * @Param: [n, edges] ==> [结点个数, 边集]
         * @return: int[] 构成最小生成树的边集
         * @Author: Aiven
         * @Date: 2019/6/27
         */
        int[] pres = new int[n]; //并查集
        int[] ranks = new int[n]; //结点的秩

        // 初始化:pres一开始设置每个元素的上一级是自己,ranks一开始设置每个元素的秩为0
        for (int i = 0; i < n; i++) {
            pres[i] = i;
            ranks[i] = 0;
        }

        //用自己定义的MyEdge类里面的compareTo排序,按边权排序
        ArrayList<MyEdge> edgesList = new ArrayList<>();
        for (int i = 0; i < edges.length; i++) {
            edgesList.add(new MyEdge(edges[i]));
        }
        // 边集从小到大排序
        Collections.sort(edgesList);

        int[][] mstEdges = new int[n - 1][3];
        int count = 0;
        for (int i = 0; i < edgesList.size(); i++) {
            int[] arr = edgesList.get(i).array;
            int a = arr[0], b = arr[1], c = arr[2];
            if (find(a, pres) != find(b, pres)) {
                unionSet(a, b, pres, ranks);
                mstEdges[count] = arr;
                count++;
            }
            if (count == n) {
                break;
            }
        }
        return mstEdges;
    }

    //并:合并两个集合,按秩合并
    public static void unionSet(int n1, int n2, int[] pres, int[] ranks) {
        int root1 = find(n1, pres);
        int root2 = find(n2, pres);
        //当两个元素不是同一组的时候才合并
        if (root1 != root2) {
            if (ranks[root1] < ranks[root2]) {
                pres[root1] = root2;
            } else {
                pres[root2] = root1;
                if (ranks[root1] == ranks[root2])
                    ranks[root1]++;
            }
        }
    }

    //查:查找元素的首级
    public static int find(int x, int[] pres) {
        int root = x;
        while (pres[root] != root)
            root = pres[root];

        //路径压缩
        int p = x;
        while (pres[p] != p) {
            int t = pres[p];
            pres[p] = root;
            p = t;
        }
        return root;
    }


}

// 边的排序类
class MyEdge implements Comparable {
    int[] array;

    MyEdge(int[] array) {
        this.array = array;
    }

    @Override
    public int compareTo(Object o) {
        o = (MyEdge) o;
        int[] arr = ((MyEdge) o).array;
        if (array[2] > arr[2]) {
            return 1;
        } else if (array[2] == arr[2]) {
            return 0;
        } else {
            return -1;
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值