您的位置:首页 > 其它

13-14寒假作业9

2014-03-03 21:22 260 查看
poj2524 并查集水题

输入点的总数,在输入几对点,表示这两个点在同一组里,问总共有多少组。

并查集是很快判断这种题的一个办法,用到了一些树的思想。首先设一个数组f[i],表示第i个点的祖宗是谁,开始的时候每个人的祖宗都是自己。一个祖宗和它的后代们就是在同一个集合里的所有点。

每输入两个个数字,我们都找到他们的祖宗是谁,如果是同一个祖宗,说明他们是同一个集合的,否则令一个数的祖宗是另一个数。

int find(int x)

{

return x==f[x]?x:f[x]=find(f[x]);

}

这个函数的返回值是点x的祖宗。最坏的时候,可能这棵树是一个链表,上边的函数就避免了一个问题,递归找到最后的祖宗,返回的时候把所有的点都直接变成他的儿子。这个函数让我获益不少。

#include<cstdio>

#include<cstring>

const int maxn=1000;

int x,y,OK,temp;

int f[maxn];

bool u[maxn];

int find(int x)

{

return x==f[x]?x:f[x]=find(f[x]);

}

int main()

{

int t=1,i,a1,a2;

temp=1;

while(scanf("%d%d",&x,&y),x!=-1&&y!=-1)

{

if(temp&&!x&&!y)

{

printf("Case %d is a tree.\n",t++);

continue;

}

if(temp)

{

a1=a2=0;

OK=1;

memset(u,1,sizeof(u));

for(i=0;i<maxn;++i)

f[i]=i;

}

a2++;

if(temp) temp=0;

if(!x&&!y)

{

temp=1;

if(a1!=a2) OK=0;

OK?printf("Case %d is a tree.\n",t++):printf("Case %d is not a tree.\n",t++);

continue;

}

else

{

if(f[y]=find(x)==find(y)) OK=0;

if(u[x]) {a1++; u[x]=0;}

if(u[y]) {a1++; u[y]=0;}

}

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: