最小生成树的kruskal(克鲁斯卡尔)做法

题目:

题解涉及到的知识点:

在连通网中查找最小生成树的常用方法有两个,分别称为普里姆算法和克鲁斯卡尔算法。本文章,将讲解克鲁斯卡尔算法和其例题(怎样用它写最小生成树)。

克鲁斯卡尔算法查找最小生成树的方法是:将连通网中所有的边按照权值大小做升序排序,从权值最小的边开始选择,只要此边不和已选择的边一起构成环路,就可以选择它组成最小生成树。对于 N 个顶点的连通网,挑选出 N-1 条符合条件的边,这些边组成的生成树就是最小生成树。

 题解:

上述题目的思路:

1.输入边,用结构体储存

2.用结构体快排以边比较从小到大快排

3.建一个并查集,并初始化并查集(并查集代表两个点有没有在同一个树里面)

4.进行kruskal算法:当到了已连边的个数是点的个数-1时,就要停止循环,因为这个时候,最小生成树已经完成了,所有的并查集都连在了一起。

上述题目的代码如下

#include<iostream>
#include<algorithm>   //用到排列的要用这个头文件 
using namespace std;
int n,m,u,v,total;
struct edge{          //用结构体储存边 
	int start,to;long long val;  //分别定义边的开头,边的结尾和边的长度 
}bian[200005];
long long ans;
int f[5005];                //为(并查集)准备的数组 
bool cmp(edge a,edge b)     //边的快速排序的定义 
{
	return a.val<b.val;     //从小到大排序 
}
int find(int x)           //并查集部分,作用是:判断有没有连成一个环。 
{
	if(f[x]==x) return x;   //f[i]表示x的“上级”,即x的父亲 
	return find(f[x]);      //此处省略了else,原来应该是else  return find(f[x]); 
}
inline void kruskal()      //最小生成树的kruskal算法 
{
	for(int i=1;i<=m;i++)   //m表示边 
	{
		u=find(bian[i].start);  //边的开头 的上级 
		v=find(bian[i].to);     //边的结尾的上级  ,
		                       //目的是为了看边的开头和结尾是否在一个并查集里,他们有没有形成一个环 
		if(u==v) continue;  /*if()continue语句的作用是:
		                    如果满足if里面的条件,则不执行循环语句里面的剩余内容,跳出循环,执行下一次循环*/
		ans+=bian[i].val;   //如果不在同个并查集里面,就边的长度(权值)的叠加 
		f[u]=v;          //连接两个并查集
		total++;         //边++; 
		if(total==n-1)break;   //点-1=边,即形成了最小生成树,则退出(之后做的也没用了) 
	}	
	if(total==n-1)      //如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。
	{
	cout<<ans<<endl;
	}
	else cout<<"orz"<<endl;     //如果该图不连通则输出 orz。
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	f[i]=i;                 //初始化结点的上级就是它本身; 
	for(int i=1;i<=m;i++)
	cin>>bian[i].start>>bian[i].to>>bian[i].val;   //输入 
	sort(bian+1,bian+m+1,cmp);             //快速排序,m表示输入的边的数量 
	kruskal();          //调用函数“最小生成树的kruskal算法” 
	return 0;
} 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值