zoukankan      html  css  js  c++  java
  • 最小生成树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;
    }
    
  • 相关阅读:
    [整理]解析Json需要设置Mime
    [整理]IE11中的WebGL探秘:渲染速度超Chrome
    [转载]详解主流浏览器多进程架构:Chrome、IE
    [转载]为什么浏览器会使用多进程架构
    [整理]win7下VS2010遇到内存不足解决方发
    [整理]WebAPI中应用oData
    [转载]NodeJS优缺点及适用场景讨论
    [转载]HTML5 真的会消灭原生App吗?
    [转载]微软VS2015支持Android和iOS编程
    VC++调试基础
  • 原文地址:https://www.cnblogs.com/lifehappy/p/12601198.html
Copyright © 2011-2022 走看看