现在的位置: 首页 > 综合 > 正文

并查集(按秩合并、路径压缩)

2014年01月27日 ⁄ 综合 ⁄ 共 767字 ⁄ 字号 评论关闭

算法分类:

数据结构

算法原理:

通过find函数找出该节点的根节点,

通过UNION函数将两棵树合并。

加入rank[N]来记录每个节点的秩(即树的高度),并按秩进行合并,可避免合并时的最糟糕情况,(树形为一条直线)

通过路径压缩可以减少每次寻找根节点的次数。

算法时间复杂度:

最坏情况为O(mlogn)

一般为O(m)

代码实现:(HDU1232-畅通工程)

/*
 * HDU 1232 畅通工程
 * 并查集
 */ 
#include <iostream>
using namespace std;

const int SIZE = 1005;
int root[SIZE];
int rank[SIZE];

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

void UNION(int x, int y) {
	int f1 = find(x);
	int f2 = find(y);
	
	if (rank[f1] <= rank[f2]) {
		root[f1] = f2;
		if (rank[f1] == rank[f2]) {
			rank[f2] ++; 	
		}	
	} else {
		root[f2] = f1;
	}
};

int main()
{
	int N, M, s, e, count;
	
	while (scanf("%d%d",&N,&M)!=EOF, N) {
		for (int i = 1; i <= N; ++ i) 
			root[i] = i;
		
		for (int i = 0; i < M; ++ i) {
			scanf("%d%d",&s,&e);
			UNION(s,e);
		}
		
		count = -1;
		for (int i = 1; i <= N; ++ i) {
			if (root[i] == i) 
				++ count;
		}
		
		printf("%d\n",count);
	}
}

抱歉!评论已关闭.