最小生成树------克鲁斯卡尔算法(并查集、sort)

1.并查集

用法:一个方便归类的算法。。。

将一个复杂的图转换成一个公共父节点的图(如图所示)

具体代码:

​
int find(int x)		//并查集  
{
	int r=x,i=x,temp;
	
	if (tree[r]==r)
		return r;		
	while (tree[r]!=r)	//r 找到 最.根节点 
		r=tree[r];
	while (i!=r)	//全部变成跟节点 
	{
		temp=tree[i];	//temp 临时变量 
		tree[i]=r;
		i=temp;
	}
	return r;
}

​

2.sort排序

头文件:algorithm

基础用法:从小到大排序:sort(a,a+n);      (n指数组a的大小)

高尚用法:sort(a,a+n,compare);

其中compare是个bool函数(注意:不能用 '<='  或 '>=')

bool compare(node e1,node e2)		//sort排序---比较函数 
{
	return e1.weight<e2.weight;
}

3.克鲁斯卡尔算法

好了。。。终于到重点了。。。

 

首先,记录是以边记录

然后

用sort从小到大排序一波边的权值大小

 

接着

从小到大依次选边

如果这条边与原来选择的边构成了环,就不选这条(continue)

ps:是否构成环可用并查集完成

 

代码献上:

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

struct node
{
	int from,end,weight;
};

const int maxSize=200000;
int n,m;
int tree[maxSize+5];
node edge[maxSize+5];

bool compare(node e1,node e2)		//sort排序---比较函数 
{
	return e1.weight<e2.weight;
}

int find(int x)		//并查集  
{
	int r=x,i=x,temp;
	
	if (tree[r]==r)
		return r;
		
	while (tree[r]!=r)	//r 找到 最.根节点 
		r=tree[r];
	
	while (i!=r)	//全部变成跟节点 
	{
		temp=tree[i];	//temp 临时变量 
		tree[i]=r;
		i=temp;
	}
	return r;
}

void Kruskal()
{
	int i,sum,tot,fx,fy;
	
	tot=1;
	sum=0;
	i=0;
	
	while (tot<n)
	{
		fx=find(edge[i].from);
		fy=find(edge[i].end);	
		if (fx!=fy)
		{
			tree[fx]=fy;	//并查集合并 (这里是最.根节点的合并!!!)
			
			tot++;
			sum+=edge[i].weight;
		}
		i++;
	}
	printf("%d\n",sum);
}

int main()
{
	int i,x,y,z;
	
	freopen("a.txt","r",stdin);
	scanf("%d%d",&n,&m);
	
	for (i=0;i<m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		edge[i].from=x;	edge[i].end=y;	edge[i].weight=z;
	}
	
	sort(edge,edge+m,compare);
	
	for (i=1;i<=n;i++)
		tree[i]=i;
	
	Kruskal();
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值