Java中的Kruskal------最小生成树
- [Kruskal ------ 最小生成树/图](#Kruskal —— 最小生成树/图)
- [例题1(FROM 洛谷 P3366)](#例题1(FROM 洛谷 P3366))
图论的第一篇是前一章的 -> Java中的 Dijkstra 算法,还打算写一个Floyd,在图论的最后一章会总结三种算法在什么情况下适合使用,以及使用方法,加深记忆。
Kruskal ------ 最小生成树/图
学过离散数学的应该知道什么是最小生成树/图,假设有n个节点,画n-1条边使得该树/图最后的总权重最小的,就是最小生成。Kruskal 算法其实是图论思想和并查集 的结合。并查集不会的可以去补一下 ->Java中的并查集
例题1(FROM 洛谷 P3366)

这就是个模板题,没有什么思路,可以直接看代码
代码实现
java
import java.util.*;
import java.io.*;
public class Main{
static int [] p;
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer st;
public static void main(String [] args) throws IOException{
int n = Integer.parseInt(next());
int m = Integer.parseInt(next());
int [][] e = new int [m][3];//{u,v,w};
for(int i=0;i<m;i++){
int u = Integer.parseInt(next());
int v = Integer.parseInt(next());
int w = Integer.parseInt(next());
e[i] = new int []{u,v,w};
}
Arrays.sort(e,(a,b)->a[2]-b[2]);//将接收到的边按照权重从小到大排序
p = new int [n+1];
for(int i=1;i<=n;i++)
p[i] = i;
long ans = 0;//结果
int count = 0;//边的个数
for(int [] E:e){
int u = E[0];
int v = E[1];
int w = E[2];
if(find(u) != find(v)){//如果没在最小生成图里
union(u,v);//加进去
ans += w;//结果加上该边的权重
count++;//边数加一
if(count == n-1) break;//如果已经找到了n-1条边,提前结束,剪枝
}
}
if(count < n-1)//如果找到的边不够,说明该图不连通
System.out.print("orz");
else System.out.print(ans);
}
static int find(int x){
if(x == p[x]) return x;
else return p[x] = find(p[x]);
}
static void union(int x,int y){
int rx = find(x);
int ry = find(y);
if(rx != ry)
p[rx] = ry;
}
static String next() throws IOException{
while(st == null || !st.hasMoreTokens()){
String str = bf.readLine();
if(str == null) return null;
st = new StringTokenizer(str);
}
return st.nextToken();
}
}
进阶版: 洛谷 P2820,自行练习吧,代码我贴这里了:
java
import java.util.*;
public class Main{
static int [] p;
public static void main(String [] args){
Scanner input = new Scanner (System.in);
int n = input.nextInt();
int k = input.nextInt();
int [][] f = new int [k][3];
long sumM = 0;
for(int i=0;i<k;i++){
f[i][0] = input.nextInt();//i
f[i][1] = input.nextInt();//j
f[i][2] = input.nextInt();//m
sumM += f[i][2];
}
Arrays.sort(f,(a,b)->a[2]-b[2]);
p = new int [n+1];
for(int i=0;i<=n;i++)
p[i] = i;
long ans = 0;
int count = 0;
for(int i=0;i<k;i++){
int u = f[i][0];
int v = f[i][1];
int w = f[i][2];
if(find(u) != find(v)){
union(u,v);
ans += w;
count ++;
if(count == n-1) break;
}
}
System.out.print(sumM-ans);
}
static int find(int x){
if(x == p[x]) return x;
else return p[x] = find(p[x]);
}
static void union(int x,int y){
int rx = find(x);
int ry = find(y);
if(rx != ry)
p[rx] = ry;
}
}
只要学好并查集 so easy