Boruvka最小生成树模板

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e3 + 5;
const int maxm = 5e5 + 5;
namespace MST {
	struct edge {
		int u, v, w;
	}E[maxm];
	int n, m;
	int tot = 0;
	void addedge(int u, int v, int w) {
		E[++tot].u = u;
		E[tot].v = v;
		E[tot].w = w;
	}

	int fa[maxn];
	void init() {
		for (int i = 1; i <= n; i++) {
			fa[i] = i;
		}
	}
	int find(int x) {
		return x == fa[x] ? x : fa[x] = find(fa[x]);
	}
	int Union(int u, int v) {
		int fu = find(u), fv = find(v);
		fa[fu] = fv;
	}

	int better(int i, int j) {
		if (j == 0)return 1;
		if (E[i].w != E[j].w) {
			return E[i].w < E[j].w;
		}
		else return i < j;
	}

	int best[maxn];
	int used[maxm];

	int solve() {
		int sum = 0, merge = 0;
		bool isupdate = 1;
		while (isupdate) {
			isupdate = 0;
			memset(best, 0, sizeof best);

			for (int i = 1; i <= tot; i++) {//找到每个连通块的最短出边
				if (used[i])continue;
				int fu = find(E[i].u), fv = find(E[i].v);
				if (fu == fv)continue;

				if (better(i, best[fu]))best[fu] = i;
				if (better(i, best[fv]))best[fv] = i;
			}

			for (int u = 1; u <= n; u++) {
				if (best[u] && !used[best[u]]) {
					isupdate = 1;
					sum += E[best[u]].w;
					merge++;
					Union(E[best[u]].u, E[best[u]].v);
					used[best[u]] = 1;
				}
			}
		}
		return merge == n - 1 ? sum : -1;
	}
}
using namespace MST;
int main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, w);
	}
	init();
	int ans=solve();
	if (ans != -1) {
		cout << ans << endl;
	}
	else {
		cout << "orz\n";
	}
}

posted @ 2020-03-03 23:36  UCPRER  阅读(169)  评论(0编辑  收藏  举报