最小生成树定义:
给定一张边带权的无向图 G=(V,E),其中 V 表示图中点的集合,E 表示图中边的集合。
由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G 的最小生成树。
最小生成树应用场景:
例如在城市规划中,有 n 座城市,需要修建高速公路来连通各个城市,如何设计可使得路程修建总距离最短。可以抽象为,当前有个 n 个点的无向图,每个点之间都有一条连线,从中找出 n-1 条边,使得所有的点都在一个集合中,且集合中所有边的权值加起来最小。
也可广泛的应用于通信,电路,航线等等类似的问题。
最小生成树其他算法 最小生成树---朴素Prim算法,堆优化版Prim算法-CSDN博客
Kruskal算法
使用到并查集并查集(基本原理+示例)-CSDN博客
算法思路:
S:已加入最小生成树的点的集合
伪代码:
1.将所有的边按权重从小到大进行排序(点之间是双向的,但只需要存储一个方向的边)
2.枚举每一条边 a -> b 权重c
if a,b不联通
将这条边加入集合S (使用到并查集的方法)
最小生成树的题(都来源acwing):
1138. 城市公交网建设问题 - AcWing题库 (数据范围小,prim也可使用)
最小生成树的 题库 - AcWing
学校有 n 台计算机,编号是 1∼n,为了方便数据传输,现要将它们用数据线连接起来,同一条数据线中数据的传输可以是 双向 的。
两台计算机被连接是指它们有数据线连接。
由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。
当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。
为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。
现在由你负责连接这些计算机,任务是使任意两台计算机都连通(不管是直接的或间接的)。
输入格式
第一行为整数 n,表示计算机的数目。
此后的 n 行,每行 n 个整数,输入一个对角线上全部是0的 对称矩阵。
其中第 x+1 行 y 列的整数表示直接连接第 x 台计算机和第 y 台计算机的费用。输出格式
一个整数,表示最小的连接费用。
数据范围
2≤n≤100,
连接任意两台计算机的费用均是非负整数且不超过10000。输入样例:
3 0 1 2 1 0 1 2 1 0
输出样例:
2
import java.io.*;
import java.util.*;
class Main{
static int N = 110;
static int n,m,res;
static int[] p = new int[N];
static Queue<PII> q = new PriorityQueue<>();
public static void main(String[] args) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(in.readLine());
for(int i=1;i<=n;i++){
p[i] = i; // 初始化p[],一个点一个集合
String[] s = in.readLine().split(" ");
for(int j=1;j<i;j++){
q.add(new PII(i,j,Integer.parseInt(s[j-1]))); // 只读取左下半的数据
}
}
// kruskal算法
while(!q.isEmpty()){ // 读取所有的边
PII t = q.poll();
int a = t.a, b = t.b, c = t.c;
if(find(a)!=find(b)){ // 如果不在一个集合
p[find(a)] = find(b); // 加到一个集合
res += c; // 加上权重
}
}
System.out.println(res);
}
// 找集合的根节点
public static int find(int u){
if(p[u]!=u) p[u] = find(p[u]);
return p[u];
}
}
// 存储边
class PII implements Comparable<PII>{
int a;
int b;
int c;
public PII(int a,int b,int c){
this.a = a;
this.b = b;
this.c = c;
}
public int compareTo(PII i){
return this.c-i.c;
}
}