krusual算法实现最小生成树,其实是并查集的应用,通过对每个点用并查集组合就可以获得一棵最小生成树。
以洛谷的p3366为例子:
题目:
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式
第一行包含两个整数 N,MN,M,表示该图共有 NN 个结点和 MM 条无向边。
接下来 MM 行每行包含三个整数 Xi,Yi,ZiX 表示有一条长度为 Zi的无向边连接结点 Xi,Yi。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。
这道题,如果用collection进行排序的话会有一点小细节,如果没注意就没有AC,有3个测试点是通过不了的。
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class p3366_model {
static int[] id;
static int[] size;
public static void main(String[] args) throws Exception{
//测试用的代码,一开始并不知道bug在哪老是re,控制台输入大规模数据读不全,直接用BuffereReader读文件测试
File f = new File("P3366_2.in");
BufferedReader reader = new BufferedReader(new FileReader(f));
// BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n,m;
String[] sb = reader.readLine().split(" ");
n=Integer.parseInt(sb[0]);
m=Integer.parseInt(sb[1]);
init(n);
List<graph_edge1> l = new ArrayList<>(M);
for(int i=0;i<m;i++){
String[] sa = reader.readLine().split(" ");
int a = Integer.parseInt(sa[0]);
int b = Integer.parseInt(sa[1]);
int c = Integer.parseInt(sa[2]);
graph_edge1 g = new graph_edge1(a,b,c);
l.add(g);
}
// l.stream().sorted();
Collections.sort(l);
int res =0;
int chance = 0;
for(graph_edge1 g:l){
if(find(g.begin)!=find(g.end)){
union(g.begin,g.end);
res+=g.weight;
chance++;
}
}
if(chance<n-1) System.out.println("orz");
else System.out.println(res);
}
//接下来三个函数是并查集初始化模板
public static void init(int n){
for(int i=1;i<=n;i++){
id[i] = i;
}
}
public static int find(int x){
while(x != id[x]) x=id[id[x]];
return x;
}
public static void union(int x ,int y){
x=find(x);
y=find(y);
if(x==y) return;
id[x] = y;
}
}
//创建每个边的对象,因为要用Collections.sort()对list排序,所以要调用接口Comparable
class graph_edge1 implements Comparable<graph_edge1>{
int begin;
int end;
int weight;
public graph_edge1(int a,int b,int c){
this.begin = a;
this.end = b;
this.weight = c;
}
/*接下来就是一直bug的地方,一开始我只写了小于的情况,并没有写等于,return0,一般来说是没有问题的,但是当数据量过大,影响排序时,就会报错:java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeCollapse(TimSort.java:408)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659) */
@Override
public int compareTo(graph_edge1 o) {
if( o.weight < this.weight) return 1;
if( o.weight == this.weight) return 0;
return -1;
}
}
细节很重要。