首页 > 其他分享 >最小生成树 Kruskal

最小生成树 Kruskal

时间:2023-10-03 16:22:52浏览次数:30  
标签:连通 le int Kruskal father 最小 生成

问题引入:
有某无向图,其有n个点m条边,每条边边权w已知,求能使图连通的最小代价。
等价于 :
有一个联通图,它有n个点,把这个图去边,直到还剩n-1条边。如果现在这个图还是联通图,那么你就得到了一棵树,这棵树就是图的生成树,最小生成树就是一个图的所有生成树里这n-1条边的权值之和最小的。
人为去寻找最小连通方式!
解决方法:
思想: 贪心的按照边权从小到大加入。
过程:
1.将所有边按照边权从小到大排序。
2.选择一条当前边权最小且边的两个端点未连通的边,加入集合。
3.重复2操作;直到已选择n-1条边,算法结束。
时间复杂度O(mlogm)
分析:

  1. 对于1操作,直接使用sort排序即可。
  2. 对于2操作,难点是判断两个端点是否连通。

解决办法: 并查集

for(int i = 1; i <= n; i++)  father[i] = i;
int find(int x)
{
   if(father[x] != x) father[x] = find(father[x]);
   return father[x]; 
}

例题 最小生成树

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

输入格式

第一行包含两个整数 \(N,M\),表示该图共有 \(N\) 个结点和 \(M\) 条无向边。

接下来 \(M\) 行每行包含三个整数 \(X_i,Y_i,Z_i\),表示有一条长度为 \(Z_i\) 的无向边连接结点 \(X_i,Y_i\)。

输出格式

如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz

样例 #1

样例输入 #1

4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

样例输出 #1

7

提示

数据规模:

对于 \(20\%\) 的数据,\(N\le 5\),\(M\le 20\)。

对于 \(40\%\) 的数据,\(N\le 50\),\(M\le 2500\)。

对于 \(70\%\) 的数据,\(N\le 500\),\(M\le 10^4\)。

对于 \(100\%\) 的数据:\(1\le N\le 5000\),\(1\le M\le 2\times 10^5\),\(1\le Z_i \le 10^4\)。

样例解释:

所以最小生成树的总边权为 \(2+2+3=7\)。
AC 代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 200100;
struct node{
	int u;
	int v;
	int w;	
}e[N];
int father[N];
bool cmp(node a,node b)
{
	return a.w < b.w;
}
int find(int x)
{
	if(father[x] != x) father[x] = find(father[x]);
	return father[x];
}
int ans,cnt;
int n,m;
int main()
{
	ios::sync_with_stdio(false);
	cout.tie(NULL);
	cin>>n>>m;
	
	for(int i = 1; i <= n; i++)
	father[i] = i;
	
	for(int i = 0; i < m ; i++)
	cin>>e[i].u>>e[i].v>>e[i].w;
	
	sort(e,e + m,cmp);
	for(int i = 0 ;i < m; i++)
	{
		int fau = find(e[i].u);
		int fav = find(e[i].v);
		if(fau != fav)// 两点不连通
		{
			father[fau] = fav;//建立联通关系
			ans += e[i].w;
			cnt++;//边数 = 点数 - 1 则图恰好连通
			if(cnt == n - 1) break;
		}
	}
	if(cnt != n - 1) puts("orz");
	else cout<<ans;
	return 0;
}

标签:连通,le,int,Kruskal,father,最小,生成
From: https://www.cnblogs.com/Elgina/p/17741232.html

相关文章

  • 判别模型和生成模型
    生成模型就像它的名字可以模拟训练数据的特征分布。判别模型只能根据输入变量x判断其类别。抽象一下都是p(Y|x) ......
  • 155. 最小栈
    设计一个支持push,pop,top操作,并能在常数时间内检索到最小元素的栈。实现MinStack类:MinStack()初始化堆栈对象。voidpush(intval)将元素val推入堆栈。voidpop()删除堆栈顶部的元素。inttop()获取堆栈顶部的元素。intgetMin()获取堆栈中的最小元素。输入:["......
  • C++特种成员函数生成机制及相关原则
    C++特种成员函数生成机制及相关原则注:默认C++标准是C++11及以后的标准,因为C++11之前的标准定义的默认成员函数不包含移动构造函数和移动赋值运算符1.C++默认成员函数默认成员函数的定义:类中没有显示声明,在需要时由编译器自动生成的函数,包括默认构造函数、默认析构函数、......
  • Leaf-美团的分布式ID生成器
    简介在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店、猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息,数据库的自增ID显然不能满足需求;特别一点的如订单、骑手、优惠券也都需要有唯......
  • 153. 寻找旋转排序数组中的最小值
    已知一个长度为n的数组,预先按照升序排列,经由1到n次旋转后,得到输入数组。例如,原数组nums=[0,1,2,4,5,6,7]在变化后可能得到:若旋转4次,则可以得到[4,5,6,7,0,1,2]若旋转7次,则可以得到[0,1,2,4,5,6,7]注意,数组[a[0],a[1],a[2],...,a[n-1]]旋转一次的结果......
  • chat2db教程:根据对话内容生成SQL语句
    准备示例表--学生信息表droptableifexistsSTUDENT;CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENTCOMMENT'学生ID',nameVARCHAR(50)NOTNULLCOMMENT'学生姓名',genderVARCHAR(10)NOTNULLCOMMENT'学生性别',birthdayDATEN......
  • prim求最小生成树
    prim算法建议在kruskal算法及相关证明掌握后进行学习,这里不再赘述。前置知识暂无prim的算法步骤确定一号节点为最小生成树。找到一条由已经属于最小生成树的点集连到还不属于最小生成树的点集的边,使得这条边在这类边中权值最小。令已经属于最小生成树的点集为\(S\),还......
  • 可迭代、迭代器、生成器
    可迭代可以通过isinstance(object,Itreable)判断也可以通过如下方式判断dir()方法,如果有实现__iter__就说明是可迭代的当然也可能只是闲了__getitem__方法,尝试按顺序获取元素,也不会抛出异常因此,我们可以通过能不能用for去迭代或者使用iter()来尝试生成迭代器来......
  • VCS代码保护+SOC中的复位电路+verdi生成部分原理图+verdi查看delta cycle+自定义的原
    VCS代码保护在新思公司的一些vip的实现中,一些代码进行了加密,导致无法查看源码,加密的方法也是使用新思的工具VCS。在编译的命令行添加+protect选项,在代码前后加上编译指示,则生成对应的加密vp、svp文件,中间的部分被加密。https://blog.csdn.net/woodhorse007/article/details/524......
  • 免费 AI 代码生成器 Amazon CodeWhisperer 初体验
    文章作者:浪里行舟简介随着ChatGPT的到来,不由让很多程序员感到恐慌。虽然我们阻止不了AI时代到来,但是我们可以跟随AI的脚步,近期我发现了一个神仙AI代码生产工具CodeWhisperer,它是一项基于机器学习的服务,其根据自然语言注释和集成开发环境(IDE)中的代码,生成代码建议,帮助......