#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;
}
}