树状合并、带路径压缩的并查集可以以最大O(logN),平均O(1)的复杂度完成合并与测试操作
这个是2006年8月8日更新版,相比于2006年7月8日版,有以下改进:
1、添加求集合规模运算
2、简化代码
3、提高运行速度
4、减少占用空间
该标程经VC6.0及g++编译器编译通过
#include < cstring >
namespace UnionNS
{
/**/ /* 解决:并查集
*算法:树状、带路径压缩的并查集
*备注:by Cockerel 06-08-08
*/
const int maxV = 100 ;
int p[maxV]; // p[i]= p[i]>=0 ? 父编号 : 集合规模
// 初始化:
inline void init( int v)
{
memset(p, - 1 , sizeof (p)); // 初始化为根且规模为1
}
// 求根运算:
inline int root( int i)
{
int r;
for (r = i; p[r] >= 0 ; r = p[r]);
for (; i != r; i = p[i])
p[i] = r; // 路径压缩
return r;
}
// 判断等价
inline bool equal( int i, int j)
{
return root(i) == root(j);
}
// 求集合规模
inline size( int i)
{
return - p[root(i)];
}
// 合并
inline merge( int i, int j)
{
i = root(i); j = root(j);
if (p[i] < p[j]) // 树状合并
p[i] += p[j], p[j] = i;
else
p[j] += p[i], p[i] = j;
}
}
// 测试程序
#include < cstdio >
namespace UnionNS
{
char file[] = " unionIn.txt " ;
void test()
{
char c;
int v,u,w;
scanf( " %c " , & c);
switch (c)
{
case ' P ' :
scanf( " %d " , & v);
printf( " init: %d\n " ,v);
init(v);
break ;
case ' T ' :
scanf( " %d %d " , & u, & w);
printf(equal(u,w) ? " %d & %d: same\n " : " %d & %d: different\n " , u,w);
break ;
case ' U ' :
scanf( " %d %d " , & u, & w);
printf( " union %d & %d\n " ,u,w);
merge(u,w);
break ;
}
}
}
using namespace UnionNS;

int main()
{
freopen(file, " r " ,stdin);
while ( ! feof(stdin))
test();
return 0 ;
}
发表于 @ 2006年08月24日 00:15:00 | 评论( loading... ) | 举报| 收藏