最小生成树之kruskal算法

先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。

  时间复杂度为为O(e^2), 使用并查集优化后复杂度为 O(eloge),与网中的边数有关,适用于求边稀疏的网的最小生成树。

这个算法大概就分为以下步骤:

1、对图中的所有边按照权值大小进行排序

2、依次选择边,若与现有的边构成回路,则放弃这个边,选次小的边继续判断。若没有构成回路,则加入。

3、直到这个集合包含所有节点,即成为一颗生成树为止。

模版如下。find是并查集。u,v数组用来存每一条边的两个端点,w数组存边的权值。p[x]代表x的父节点,r用来存放排序后的边。

int u[maxn],v[maxn],w[maxn],p[maxn],r[maxn];

int cmp(const int i,int j)
{
	return w[i]<w[j];
}

int find(int x)
{
	return p[x]==x ? x:p[x]=find(p[x]);
}

int kruskal(int m)
{
	int ans=0;
	for(int i=0;i<m;i++) p[i]=i;
	for(int i=0;i<m;i++) r[i]=i;
	sort(r,r+m,cmp);
	for(int i=0;i<m;i++)
	{
		int e=r[i];
		int x=find(u[e]);
		int y=find(v[e]);
		if(x!=y)
		{
			ans+=w[e];
			p[x]=y;
		}
	}
	return ans;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值