13-14寒假作业9

来源:互联网 发布:淘宝旺铺有什么用 编辑:程序博客网 时间:2024/05/29 11:42

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


 

 

0 0
原创粉丝点击