题目描述
编程实现Kruskal算法,求图的最小生成树(MST)的权重。
输入
每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。
输出
最小生成树的权重。
样例输入
3 3
0 1 10
0 2 15
1 2 50
样例输出
25
代码实现
import java.util.Scanner;
public class Main {
//建类,边
public static class edge{
int x,y,w;
}
static int pa[];
static int rank[];
//计算总权重
static int sum;
//路径压缩的查找
public static int find_set(int x) {
//x的父节点不等于自己,即不是根节点
if(x != pa[x])
//递归返回根节点
pa[x] = find_set(pa[x]);
return pa[x];
}
//按秩合并,查找
public static void union_set(int x,int y,int w) {
//返回根节点
x = find_set(x);
y = find_set(y);
//已经合并的情况,避免形成换
//避免重复加入
if(x==y)
return;
//合并,秩比较高的的根节点作为根节点
if(rank[x]>rank[y])
pa[y] = x;
else {
//将x的父节点变成y
pa[x] = y;
if(rank[x]==rank[y])
//y的树的秩增加
rank[y]++;
}
//边加入后,权重要加进去
sum += w;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
int m = sc.nextInt();
//建立数组
edge e[] = new edge[101];
pa = new int[101];
rank = new int[101];
//初始化
for(int i=0;i<n;i++) {
pa[i] = i;
rank[i] = 0;
}
//每个数组放对象
for(int i=0;i<m;i++)
e[i] = new edge();
//为每一个对象赋值
for(int i=0;i<m;i++) {
e[i].x = sc.nextInt();
e[i].y = sc.nextInt();
e[i].w = sc.nextInt();
}
//排序,按照边的权重由小到大
for(int i=0;i<m;i++)
for(int j=0;j<m-i-1;j++) {
if(e[j].w > e[j+1].w) {
int t = e[j].w;
e[j].w = e[j+1].w;
e[j+1].w = t;
int t1 = e[j].x;
e[j].x = e[j+1].x;
e[j+1].x = t1;
int t2 = e[j].y;
e[j].y = e[j+1].y;
e[j+1].y = t2;
}
}
sum = 0;
for(int i=0;i<m;i++)
//遍历每一条边
union_set(e[i].x, e[i].y, e[i].w);
//输出最小生成树的总权重
System.out.println(sum);
}
}
}