最小生成树定义:
给定一张边带权的无向图 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也可使用)
1147. 构造完全图 - AcWing题库
最小生成树的 题库 - AcWing
例题: 1139. 最优布线问题 - 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;}
}