Minimum Spanning Tree
Prim 在稠密图中比 Kruskal 优,在稀疏图中比 Kruskal 劣。Prim 是以更新过的节点的连边找最小值,Kruskal 是直接将边排序。
Prim
时间复杂度:\(O(n^2)\),通过堆优化可以变成 \(O(mlogn)\)
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector g(n, vector<int>(n, 2e9));
for (int i = 0; i < m; i ++ ){
int u, v, w;
cin >> u >> v >> w;
u -- , v -- ;
g[u][v] = g[v][u] = min(g[u][v], w);
}
auto prim = [&](){
vector<int> d(n, 2e9);
d[0] = 0;
vector<bool> vis(n);
for (int i = 0; i < n; i ++ ){
int k = -1;
for (int j = 0; j < n; j ++ ){
if (!vis[j] && (k == -1 || d[j] < d[k])){
k = j;
}
}
if (k == -1 || d[k] == 2e9){
cout << "orz\n";
return;
}
vis[k] = true;
for (int j = 0; j < n; j ++ ){
if (!vis[j]){
d[j] = min(d[j], g[k][j]);
}
}
}
int ans = 0;
for (int i = 1; i < n; i ++ ){
ans += d[i];
}
cout << ans << "\n";
};
prim();
return 0;
}
Kruskal
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 2e5 + 10;
LL n, m, p[N];
struct Edge{
int u, v, w;
bool operator < (const Edge &x) const{
return w < x.w;
}
}e[N];
LL get(LL x){
return (x == p[x] ? x : (p[x] = get(p[x])));
}
void kruskal(){
int cnt = 0, ans = 0;
iota(p + 1, p + n + 1, 1);
for (int i = 0; i < m; i ++ ){
int a = get(e[i].u), b = get(e[i].v);
if (a != b){
p[a] = b;
ans += e[i].w;
cnt++;
}
}
if (cnt < n - 1) cout << "orz\n";
else cout << ans << "\n";
}
int main(){
cin >> n >> m;
for (int i = 0; i < m; i ++ ){
int u, v, w;
cin >> u >> v >> w;
e[i] = {u, v, w};
}
sort(e, e + m);
kruskal();
return 0;
}
模板:
Prim: https://www.acwing.com/problem/content/860/
Kruskal: https://www.acwing.com/problem/content/861/
洛谷模板:https://www.luogu.com.cn/problem/P3366