最小生成树(Kruskal)

算法分类:

贪心


算法原理:

先从对权以非降序排列着手。接着从由图的顶点组成而不包含边的森林(V,T)开始,重复下面的这一步,知道(V,T)被换成一棵树:

设(V,T)是到现在为止构建的森林,e∈(E-T)为当前考虑的边,如果把e加到T中不生成一个回路,那么将e加入到T,否则丢弃e。

这个处理在恰好加完n-1条边后结束。

概括如下:

1. 对G的边以非降序权重排列;

2. 对于排序表中的每条边,如果现在把它放入T不会形成回路的话,则把它加入到生成树T中;否则将它丢弃。


算法时间复杂度:

O(mlogm) m为边数

则m可以像n(n-1)/2那么大,则时间复杂度为O(n平方logn)

m也可以是平面的,那么时间复杂度为O(nlogn)


代码实现:(HDU1233)

/* HDU 1233 还是畅通工程 
 * 最小生成树 Kruskal 
 */
#include <iostream>
#include <algorithm>
using namespace std;

const int SIZE = 105;
int root[SIZE];

struct _Edge {
	int s, e, v;	
}E[SIZE*(SIZE-1)/2];

bool cmp(const _Edge a, const _Edge b) {
	return a.v < b.v;	
}

int find(int x) {
	int y = x;
	while (root[y] != y) {
		y = root[y];	
	}
	
	return y;
};

int Kruskal(int N, int index) {
	for (int i = 1; i <= N; ++ i) 
		root[i] = i;
	
	int EDGE = 0, value = 0;
	sort(E, E+index, cmp);
	
	for (int i = 0; i < index && EDGE < N-1; ++ i) {
		int f1 = find(E[i].s);
		int f2 = find(E[i].e);
		
		if (f1 != f2) {
			root[f1] = f2;
			value += E[i].v;
			++ EDGE;	
		}	
	}
	
	return value;
};

int main()
{
	int N, s, e, v;
	while (scanf("%d",&N)!=EOF, N) {
		int len = N*(N-1)/2;
		for (int i = 0; i < len; ++ i) {
			scanf("%d%d%d",&s,&e,&v);
			E[i].s = s;
			E[i].e = e;
			E[i].v = v;	
		}
		
		int result = Kruskal(N, len);
		printf("%d\n",result);	
	}
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值