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/ (讲解关于并查集基础和几种初始化、路径压缩方式)