最小生成树算法 Kruskal算法

在最小生成树的问题中,我们常常不必把生成树表示出来,一般是计算生成树权值之和等问题
Kruskal算法就是把所有边排序一下,从小到大将边放到生成树当中,但是要满足将边放入后不形成环的条件。
两个要点:
1. 要先将所有的边进行排序
2. 利用并查集来快速判断两个点是否在同一颗树当中,如果在的话,边放入必然会产生环

利用Kruskal算法计算最小生成树的权值总和
注意:这个问题我们不需要把图建立出来

#include <iostream>
#include <algorithm> 
using namespace std;

int parent[1005];      //并查集的实现数组,开的大小为点的个数
int find(int p)
{
	if( p!=parent[p] ) parent[p]=find( parent[p] );
	return parent[p];
}

struct node{        //node为边,参数为边连着的两个点和权值,开的大小为边的个数
	int x;
	int y;
	int v;
	bool operator<(const node &n) const
	{
		return v<n.v;
	}
}p[100005];

int main()
{
	int n,m,ans = 0;
	cin >> n >> m;
	for( int i = 1 ; i <=n ; i++ )
	{
		parent[i] = i;       //一开始每一个点都是一棵树
	} 
	for( int i = 0 ; i < m ; i++ )
	{
		cin >> p[i].x >> p[i].y >> p[i].v;
	}
	sort(p,p+m);      //将边进行排序
	for( int i = 0 ; i < m ; i++ )
	{
		int rootx = find(p[i].x);
		int rooty = find(p[i].y);
		if( rootx != rooty )     //如果这两个点不在同一棵树上
		{
			parent[rootx] = rooty;    //把一颗树连到另一颗树上
			ans += p[i].v;
			n--;     //树的个数减少1
		}
		if( n==1 ) break;     //如果只剩下一颗树了,break出去
	}
	cout << ans << endl;
	return 0;
}

时间开销主要在对边的排序上,所以时间复杂度为Elog(E),E为图的边数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值