import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.PriorityQueue;
/**
* @author wangshaoyu
*/
public class P3366最小生成树 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
public static void main(String[] args) throws IOException {
int n = nextInt();
int m = nextInt();
EdgeWeightedGraph G = new EdgeWeightedGraph(n);
for (int i = 0; i < m; i++) {
int v = nextInt() - 1;
int w = nextInt() - 1;
int weight = nextInt();
G.addEdge(v, w, weight);
}
Kruskal kru = new Kruskal(G);
int ans = 0;
for (Edge e : kru.queue) {
ans += e.weight;
}
if (kru.queue.size() == G.v - 1) {
System.out.println(ans);
}
else {
System.out.println("orz");
}
}
}
class Edge implements Comparable<Edge> {
int v;
int w;
double weight;
public Edge(int v, int w, double weight) {
this.v = v;
this.w = w;
this.weight = weight;
}
// 返回边的其中一个顶点
int either() {
return v;
}
// 返回与v不同的另一个顶点
int other(int v) {
if (v == this.w) {
return this.v;
}
return this.w;
}
@Override
public int compareTo(Edge o) {
return Double.compare(this.weight, o.weight);
}
}
/**
* 加权无向图的实现
*/
class EdgeWeightedGraph {
int v;
ArrayList[] adj;
public EdgeWeightedGraph(int v) {
this.v = v;
adj = new ArrayList[v];
for (int i = 0; i < v; i++) {
adj[i] = new ArrayList();
}
}
void addEdge(int v, int w, double weight) {
Edge e = new Edge(v, w, weight);
adj[v].add(e);
adj[w].add(e);
}
}
// 并查集
class UnionFind {
int[] parent;
int[] size; // 根结点对应的分量的大小
int count; // 连通分量的数量
public UnionFind(int n) {
parent = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
for (int i = 0; i < n; i++) {
size[i] = 1;
}
count = n;
}
int find(int p) {
while (parent[p] != p) {
p = parent[p];
}
return p;
}
boolean isConnected(int p, int q) {
return find(p) == find(q);
}
void union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) {
return;
}
// 让小的指向大的
if (size[pRoot] < size[qRoot]) {
parent[pRoot] = qRoot;
size[qRoot] += size[pRoot];
}
else {
parent[qRoot] = pRoot;
size[pRoot] += size[qRoot];
}
count--;
}
}
class Kruskal {
ArrayDeque<Edge> queue; // 存放最小生成树中的边
public Kruskal(EdgeWeightedGraph G) {
queue = new ArrayDeque<>();
PriorityQueue<Edge> pq = new PriorityQueue<>();
UnionFind uf = new UnionFind(G.v);
// 将所有的边都加入最小堆中,这样子每条边会加两次
for (ArrayList<Edge> list : G.adj) {
for (Edge e : list) {
pq.add(e);
}
}
while (! pq.isEmpty() && queue.size() < G.v - 1) {
Edge e = pq.poll();
int v = e.either();
int w = e.other(v);
if (uf.isConnected(v, w)) {
continue;
}
uf.union(v, w);
queue.add(e);
}
}
}
kruskal 算法求最小生成树 Java
最新推荐文章于 2023-09-20 22:38:09 发布