#include <stdio.h>
#include <string.h>
/* 并查集
* 算法:树状、带路径压缩的并查集 参考严蔚明数据结构等价类一章
* 备注:by king821221 07-12-27
*/
template<int m> class unionSet
{
public:
//建立一个新的集合
void MAKE_SET(int size)
{
if(size>0)
memset(arr,-1,size*sizeof(int));
}
//将包含x和y的动态集合(比如说Sx和Sy)合并为新的集合。结果的集合代表是Sx并Sy的某个成员。
void UNION(int x,int y)
{
int sx = FIND_SET(x);
int sy = FIND_SET(y);
if(sx==sy)
return;
if(arr[sx]>=arr[sy])
{
//x所在集合规模不大于y所在集合规模
arr[sy] +=arr[sx];
arr[sx] = sy;
}
else
{
//x所在集合规模大于y所在集合规模
arr[sx]+=arr[sy];
arr[sy] = sx;
}
}
//返回一个指向包含i的惟一集合代表的指针。(用于判等)
int FIND_SET(int i)
{
int j = i;
int k = i;
while(arr[j]>=0)
{
j = arr[j];
}
while(k!=j)
{
arr[k] = j;
k = arr[k];
}
return j;
}
//返回集合的规模
int SIZE(int x)
{
return -arr[FIND_SET(x)];
}
protected:
int arr[m]; //arr[i]>=0?父节点:集合规模的负数
};
/*
int main(int argc,char **argv)
{
unionSet<1000> uset;
uset.MAKE_SET(3);
uset.UNION(0,2);
uset.UNION(0,1);
uset.UNION(1,2);
printf("%d/n",uset.FIND_SET(1));
printf("%d/n",uset.SIZE(0));
return 0;
}
*/
下面是从别人文章上摘录的一个实现
namespace UnionNS {
/**/ /* 解决:并查集
*算法:树状、带路径压缩的并查集
*备注:by Cockerel 06-08-27
*/
const int maxV = 100 ;
int p[maxV]; // p[i]= p[i]>=0 ? 父编号 : 集合规模
// 初始化:
inline void init()
{
memset(p, - 1 , sizeof (p)); // 初始化为根且规模为1
}
// 求根运算:
inline int root( int i)
{
int j,r;
for (r = i; p[r] >= 0 ; r = p[r]);
for (; i != r; i = j)
j = p[i],p[i] = r; // 路径压缩
return r;
}
// 判断等价
inline bool equal( int i, int j)
{
return root(i) == root(j);
}
// 求集合规模
inline int size( int i)
{
return - p[root(i)];
}
// 合并
inline void merge( int i, int j)
{
i = root(i); j = root(j);
if (i == j) return ;
if (p[i] < p[j]) // 树状合并
p[i] += p[j], p[j] = i;
else
p[j] += p[i], p[i] = j;
}
}