大家好,我是被白菜拱的猪。
一个热爱学习废寝忘食头悬梁锥刺股,痴迷于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;
}
}
}