思路:先把边按照权值进行排序,用贪心的思想优先选取权值较小的边,并依次连接,若出现环则跳过此边(用并查集来判断是否存在环)继续搜,直到已经使用的边的数量比总点数少一即可。
模板题目传送门:
P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Kruskal {
static int[] f;
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int n = (int)in.nval;
in.nextToken();
int m = (int)in.nval;
Edge[] e = new Edge[m + 1];
for(int i = 1; i <= m; ++i) {
e[i] = new Edge();
in.nextToken();
e[i].u = (int)in.nval;
in.nextToken();
e[i].v = (int)in.nval;
in.nextToken();
e[i].w = (int)in.nval;
}
//按边权排序(升序)
Arrays.sort(e, 1, m + 1, (a,b)-> {
return a.w - b.w;
});
f = new int[10005];
int ans = 0;
int k = 1;
//并查集初始化
for (int i = 1; i <= n; i++) f[i] = i;
for(int i = 1; i <= m; ++i) {
int l = find(e[i].u);
int r = find(e[i].v);
if (l != r) { //若两点未联通则联合
f[r] = l;
ans += e[i].w; //累加权值
++k; //已连接点+1
if (k == n) {
break;
}
}
}
if (k == n) {
out.println(ans);
} else {
out.println("orz");
}
out.flush();
}
private static int find(int x) {
return f[x] == x ? x : (f[x] = find(f[x]));
}
}
class Edge {
int u,v,w;
}
时间:2022-6-16 21:21