DGZX1522 - 并查集在kruskal中的应用

并查集的简单应用。

Kruskal是求最小生成树的经典算法之一,如果忘记了,先做一下DGZX1042。

Kruskal中每次挑选一条边加入最小生成树,就相当于将该边两个端点所在集合合并。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;

int pa[3001];
int rank[3001];
int n, m;
int ans;// answer
int tot;// total
struct node{ int x, y, z; };
node tn[50000];

int cmp(const void *pa, const void *pb)
{
	node *na = (node*)pa;
	node *nb = (node*)pb;
	return na->z - nb->z;
}
int Find(int x)
{
	int y = x;
	while (pa[y]!=0)// 寻找根
	{
		y = pa[y];
	}
	int root = y;// 保存根		
	int w;
	y = x;// 复位
	while (pa[y]!=0)// 执行路径压缩
	{
		w = pa[y];
		pa[y] = root;
		y = w;
	}
	return root;
}
void Union(int x, int y, int w)
{
	int u = Find(x), v = Find(y);
	if (u==v) return;
	if (rank[u]<=rank[v])
	{
		pa[u] = v;
		if (rank[u]==rank[v])// 树高相等时,合并后树会长高
			rank[v]++;
	}
	else
	{
		pa[v] = u;
	}
	tot++; ans += w;
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=0; i<m; i++)
		scanf("%d%d%d",&tn[i].x,&tn[i].y,&tn[i].z);
	for (int i=1; i<=n; i++)// 各个子树高度初始化为 1
		rank[i] = 1;
	qsort(tn,m,sizeof(node),cmp);
	for (int i=0; i<m; i++)
	{
		Union(tn[i].x,tn[i].y,tn[i].z);
		if (tot==n-1) break;
	}
	printf("%d\n", ans);
	return 0;
}

 

posted @ 2013-12-19 19:56  莞中OI  阅读(314)  评论(0)    收藏  举报