洛谷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;
}