zoukankan      html  css  js  c++  java
  • 【算法】最小生成树-Kruskal算法

    : 连通且不含环的图

    生成树:给定无向图G=(V,E),连接G中所有点,且边集是E的子集的树

    最小生成树(MST):权值最小的生成树

    Kruskal算法

    ①将所有边按从小到大排列

    ②依次考察每条边((u,v))。若(u)(v)在同一个连通分量中,加入((u,v))会成环,因此不能选择;否则,加入((u,v))一定是最优的(假设不加入这条边能得最优解T,则(T+(u,v))一定有且只有一个环,且这个环中至少有一条边((u',v'))的权值(≥(u,v))

    关于连通分量的判断与合并,使用并查集。

    并查集将每个连通分量看成一个包含该分量中所有点的集合,这些点之间两两连通(强连通?),只需要选其中一个点作为集合的代表即可(也就是缩点)。

    //并查集
    //p[x]保存结点x的祖先
    int find(int x) {return p[x] == x ? x : p[x] = find(p[x]);}
    
    //最小生成树Kruskal算法
    int u[maxn], v[maxn];//第i条边的两个端点的序号
    int w[maxn];//第i条边的权值
    int cmp(const int i, const int j) { return w[i] < w[j]; }
    int find(int x) {return p[x] == x ? x : p[x] = find(p[x]);}
    int Kruskal() {
    	int ans = 0;
    	for (int i = 0; i < n; i++) p[i] = i;
    	for (int i = 0; i < m; i++) r[i] = i;
    	sort(r, r + m, cmp);
    	//实际上是对w数组排序,但将结果顺序的下标保存在r数组中
        //如w[4]={4,2,1,0},排序后r数组储存的是{3,2,1,0}
    	for (int i = 0; i < m; i++) {
    		int e = r[i];//取边(u,v),记为e
    		int x = find(u[e]);//找出e的一个端点u的所在集合编号
    		int y = find(v[e]);//找出e的另一个端点v的所在集合编号
    		if (x != y) {//如果不在同一个集合
    			ans += w[e];//最小生成树的总权值更新
    			p[x] = y;//合并
    		}
    	}
    	return ans;
    }
    
  • 相关阅读:
    scrapy Request方法
    from lxml import etree报错
    python文件管道 下载图集
    scrapy基本爬虫,采集多页
    python操作excel xlwt (转)
    matplotlib 设置标题 xy标题等
    matplotlib 饼状图
    acwing 600. 仰视奶牛
    LeetCode 684. 冗余连接
    LeetCode 200. 岛屿数量
  • 原文地址:https://www.cnblogs.com/streamazure/p/12911636.html
Copyright © 2011-2022 走看看