hdu 1232 畅通工程

1.题目

http://acm.hdu.edu.cn/showproblem.php?pid=1232

2.分析

简单的并查集题目。将每一条道路的关系按照:(小,大)的关系处理,然后将M条道路按照所给关系建立并查集集合,最后并查集中集合数目-1就是需要添加的道路个数;

3.复杂度

空间复杂度为O(N),建立一个集合的时间复杂度为O(1),N次合并M次查找的时间复杂度为O(MAlpha(N)),这里Alpha是Ackerman函数的某个反函数,在很大的范围内(人类目前观测到的宇宙范围估算有10的80次方个原子,这小于前面所说的范围)这个函数的值可以看成是不大于4的,所以并查集的操作可以看做是线性的。

4.涉及内容

数据结构:并查集

5.感想

属于基础练习,但是发现了两种并查集初始化方式:

第一种,父节点初始化为自己,然后在查找的时候可以利用递归进行路径压缩;(压缩代码如下)

int Find(int x)
{
	if (x != parent[x])
	{
		parent[x] = Find(parent[x]); //这个回溯时的压缩路径是精华,使用前提是parent[x]=x,即根节点的父节点是他自己,否则只能使用上边的那个
	}
	return parent[x];
}

第二种,父节点初始化为-1,然后集合父节点用负数的绝对值保存该集合中元素数目;(统计个数代码如下)

void Union(int Root1, int Root2) {
	//按Union的加权规则改进的算法
	if(Root1 == Root2)  
        return;
	int temp = parent[Root1] + parent[Root2];//使用负数表示子节点个数
	if ( parent[Root2] < parent[Root1] ) {//父节点都是负数,所以谁的小就表示谁的点多
		parent[Root1] = Root2; //Root2中结点数多
		parent[Root2] = temp; //Root1指向Root2
	}
	else {
		parent[Root2] = Root1; //Root1中结点数多
		parent[Root1] = temp; //Root2指向Root1
	}
}

6.代码

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <functional>
using namespace std;
int parent1232[1000];
void swap1232(int &a,int &b)
{
	if(a>b)
		a=a+b,b=a-b,a=a-b;
}
void makeset1232()
{
	for(int i=0;i<1000;++i)
		parent1232[i]=-1;
}
int find1232(int x)
{
	int r=x,q;
	while(parent1232[r]>0)
		r=parent1232[r];
	while(x!=r)
	{
		int q=parent1232[x];
		parent1232[x]=r;
		x=q;
	}
	return r;
}
void union1232(int r1, int r2) {
	int x=find1232(r1);
	int y=find1232(r2);
	if(x == y && x!=-1)  
        return;
	int temp=parent1232[x]+parent1232[y];
	if(parent1232[x]<parent1232[y])
	{
		parent1232[y]=x;
		parent1232[x]=temp;
	}
	else
	{
		parent1232[x]=y;
		parent1232[y]=temp;
	}
}
int main()
{
	long N,M;int a,b;
	while(scanf("%ld %ld",&N,&M)!=EOF)
	{
		makeset1232();
		if(N==0) break;
		for(long i=0;i<M;++i)
		{
			scanf("%d %d",&a,&b);
			swap1232(a,b);
			union1232(a,b);
			//printf("%d %d\n",a,b);
		}
		printf("%d\n",count_if(parent1232+1,parent1232+N+1,bind2nd(less_equal<int>(),-1))-1);
	}
	return 0;
}

7.参考文献

http://dongxicheng.org/structure/union-find-set/   (讲解关于并查集时间复杂度和第一种初始化方式)

http://mindlee.net/2011/10/21/disjoint-sets/   (讲解关于并查集基础和几种初始化、路径压缩方式)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值