最小生成树KrusKal算法(并查集)

洛谷p1111链接
克鲁斯卡尔算法的思路就是由森林变成树的过程,其中最主要的就是贪心和并查集的应用。
我们知道链接n个点需要n-1条边,这就满足的最后生成的是一颗树,而不是一个环。在这n-1条边的选择上我们又要尽可能的让边的权重小,于是我们不难想到先对边的权重进行升序排序。然后再去判断这条边的两个点在不在一颗树上,如果不在就连接这两颗树。 如果在就舍弃这条边继续找下一条边,当联通的边等于n-1时,这就是我呢最终得到的最小生成树。也就是我们最后的答案。
在这里插入图片描述
下面时最后的代码,

#include<bits/stdc++.h>
using namespace std;
struct road {
	int begin,end,value;
}a[100010];
int n,m,f[1010];
bool cmp(road x,road y) {
	return x.value < y.value;
}
void init() {
	for(int i = 1; i <= n; i++)
		f[i] = i;
}
int find(int x) {//查找根节点,这里不用递归,防止递归深度过深,超时, 
	int fx = x;
	while(fx != f[fx])
		fx = f[fx];
	while(f[x] != fx) {
		x = f[x];
		f[x] = fx;
	}
}
int main() {
	cin >> n >> m;
	for(int i = 0; i < m; i++)
		cin >> a[i].begin >> a[i].end >> a[i].value;
	init();//初始化并查集的根结点。 
	sort(a,a + m,cmp);//排序,让value权重最小的有限在前。
	int maxn = 0,sum = 0;//设置最大的权重的为0,方便后面比对 ,同时当前变数设置为0, 
	for(int i = 0; i < m; i++) {
		int fbegin = find(a[i].begin);
		int fend = find(a[i].end);
		if(fbegin != fend) {
			f[fend] = fbegin;//连接两颗树,
			sum++;//边的树加一。
			maxn = max(maxn, a[i].value);//找到在这棵树上的最大权重边。 
		}
		if(sum == n - 1)//森林变成树,提前break; 
			break;
	}
	cout << maxn <<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/lifehappy/p/12601198.html