带权并查集,主要是来处理集合元素与元素之间的关系,或者说元素与元素连线之间的权值,
板子是这样的
int find(int x) {
if (x == root[x]) return x;
else {
int t = find(root[x]);
sum[x] += sum[root[x]];
root[x]=t;
return root[x];
}
}
sum[i]里面用来存放i结点到根节点的权值和,emmm,说这么多看例题。这个题特别坑人,写的时候TLE无数次,最后缓了过来,我模板写错了。。。。。。。。
poj 1988Cube Stacking
大意 是移动箱子,刚开始每个箱子算一列,有两种操作,m x,y,将x列的箱子放y上。c x,查询x这个箱子,下面有多少个箱子。
sum 是计算这列一共有多个箱子,d[i]计算i上面有多少个箱子。sum[find(x)]-d[i]-1,就是输出的结果
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int root[30009],mmax,sum[30009],d[30009];
int find(int x)
{
if(x==root[x])
return x;
int fx=find(root[x]);
d[x]+=d[root[x]];
root[x]=fx;
return root[x];
}
void join(int x,int y)
{
int xx=find(x);
int yy=find(y);
if(xx!=yy)
{ root[yy]=xx;
d[yy]=sum[xx];
sum[xx]+=sum[yy];
}
}
int main(){
int t,n,mm;
scanf("%d",&t);
char ch[3];
for(int i=1;i<=30000;i++)
{
root[i]=i;
d[i]=0;
sum[i]=1;
}
while(t--)
{ int x,y;
scanf("%s",ch);
if(ch[0]=='M')
{
scanf("%d %d",&x,&y);
join(x,y);
}
else if(ch[0]=='C')
{ scanf("%d",&x);
printf("%d\n",sum[find(x)]-d[x]-1);
}
}
return 0;
}