简介
最小生成树处理的是无向图
常用算法:
- Prim算法 O(v²)适合稠密图
- Kruskal(克鲁斯卡尔)算法O(eloge)适合稀疏图
1.Prim算法
思想
贪心:将一点加入集合S,根据临边更新其他点到该集合的距离。找出最短距离,并将对应点加入集合S。重复以上步骤,加入集合S外的顶点,直至加入所有点或者发现非联通。
伪代码
dist[i] <- 正无穷
for (i=0; i < n; i++) // 迭代n次,加入n个点
t <- 找到集合外距离最近的点 //s[t]为false,且dist[i]最小的点
用 t 更新其他点到集合的距离
s[t] = true
时间复杂度:O(v²)
代码
/*
S:当前已经在联通块中的所有点的集合
1. dist[i] = inf
2. for n 次
t<-S外离S最近的点
利用t更新S外点到S的距离
st[t] = true
n次迭代之后所有点都已加入到S中
联系:Dijkstra算法是更新到起始点的距离,Prim是更新到集合S的距离
*/
const int N = 510, INF = 0x3f3f3f3f;
int n, m; // n个点,m条边
int g[N][N];// 邻接矩阵
int dist[N]; // 存储其他点到集合S的距离
bool st[N]; // 是否在集合内
int prim(){
memset(dist, INF, sizeof dist);
int res = 0;// 如果图不连通,返回INF,否则返回res
for (int i = 0; i<n; i++){ // n次迭代,将n个点加入集合
int t = -1; // 找到距离集合最近的点
for (int j =1; j <= n; j++){
if (!st[j] && (t == -1 || dist[t] > dist[j])){
t = j;
}
}
// 没有距离集合S小于INF的点
if (i && dist[t] == INF) return INF; // 不连通
if (i) res += dist[t];
st[t] = true;
// 更新到集合S的最短距离
for (int j = 1; j <=n; j++) dist[j] = min(dist[j], g[t][j]);
}
return res;
}
2.Kruskal算法
思想
贪心:将图中的每个edge按照权重大小进行排序,每次从边集中取出权重最小且两个顶点都不在同一个集合的边加入生成树中!注意:如果这两个顶点都在同一集合内,说明已经通过其他边相连,因此如果将这个边添加到生成树中,那么就会形成环!重复直至所有边被处理过。
可以通过并查集实现。
伪代码
将所有边按权重从小到大排序 O(mlogm)
枚举每条边a <--> b,权重w
if a,b不连通 (a、b不在同一个并查集内)
将这条边加入集合中(合并a、b集合)
时间复杂度:O(elge)
代码
/*
res 最小生成树中的权重之和
cnt 当前加了多少条边
1.将所有边按权重排序O(mlogm)
2.枚举每条边(并查集应用)
if a,b 不连通
加入集合
3.需重载<
bool operator < (const Edge &C) const {
return w < C.w;
}
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10, M = 2e5+10, INF = 0x3f3f3f3f;
int n, m; // n个点,m条边
int f[N]; // 并查集
struct Edge{
int u, v, w;
bool operator < (const Edge&e) const{
return w < e.w; // 按权重从小到大排序
}
}edges[M];
int find(int x){
if (x == f[x]) return x;
return f[x] = find(f[x]);
}
int kruskal(){
sort(edges, edges+m);
for (int i =0; i<= n; i++)f[i] = i; // 初始化并查集
int res = 0, cnt = 0; // res:最小生成树权重之和;cnt:增加了多少条边
for (int i = 0; i <m; i++){
auto e = edges[i];
int p = find(e.u), q = find(e.v);
if (p != q){
f[q] = p;
res += e.w;
cnt++;
}
}
if (cnt < n-1) return INF;//集合内边数小于 n-1 ,不连通
return res;
}