您的位置:首页 > 其它

hdu2818 并查集

2016-03-28 01:14 239 查看
1、题目大意:

john 正在玩积木,有N个积木编号为1、、、N,分成N堆,每堆只包含一个积木,然后做P次操作,操作分为2种,

M X Y:把包含X的一堆放到包含Y的一堆上,如果XY同在一堆上,不做处理

C X:计算出X积木下边有多少个积木

每次遇到C操作,输出数量

遇到的问题:

第一个:数据的n有0的点,这个是数据的问题

第二个:有一个比较隐秘的bug,如果给出两块石头,且他们已经属于一个集合的话便不要做任何操作,我就是被这个数据卡住了,这里没注意的话在poj是能够ac的

思路:用a数组记录每一个块最上面的跟,用b数组记录最下面的根;用sum数组记录每个点到所在块最上面的根的距离,然后将给出的点point求出所在块的最下面的跟point1;sun[point1]-sum[point]就是所求答案;

代码:

#include<stdio.h>
int a[30005],b[30005],sum[30005],reg[30005];
int find(int tt) //求最上面的根,并计算tt点到根的距离;
{
if(tt==a[tt])
return tt;
int t=a[tt];
a[tt]=find(a[tt]);
sum[tt]+=sum[t];
return a[tt];
}
int find1(int tt) //求出tt最下面的根;
{
if(tt!=b[tt])
{
b[tt]=find1(b[tt]);
}
return b[tt];
}
void sort(int x,int y,int za,int zb)  //求出y到x的距离
{
a[y]=x;
sum[y]+=reg[x];
reg[x]=reg[x]+reg[y]; //reg函数记录每一个块点的数目,并且只有块最上面的点才记录;
reg[y]=0;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
int i,j;
char c;
int za,zb;
for(i=0;i<30005;i++)//切记从0开始
{
a[i]=i;
sum[i]=0;
b[i]=i;
reg[i]=1;
}
while(n--)
{
getchar();
scanf("%c",&c);
if(c=='M')
{
scanf("%d%d",&za,&zb);
int x=find(za);
int y=find(zb);
if(x==y)  //如果给出的两个数在同一个块,则无需操作;
continue;
int tx=find1(za);
int ty=find1(zb);
b[tx]=ty;
sort(x,y,za,zb);
}
else
{
scanf("%d",&za);
int zz=find1(za);
int aa=find(za);
int bb=find(zz);
printf("%d\n",sum[zz]-sum[za]);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: