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

posted on 2022-01-31 14:35  Hamine  阅读(79)  评论(0编辑  收藏  举报