并查集入门题集 POJ1611 POJ1703 POJ2524 POJ1182

这几道题都是POJ中入门级别的并查集题目……一一道来


http://blog.csdn.net/dellaserss/article/details/7724401这个写的特别好,基本上开完就能懂并查集的基本思想。


POJ1161 The Suspects

题意说是传染SARS其实就是找组织门派的……给出两个关系在一组的话,比较它们的find是否相等,相等不管了,不相等合并到一起并进行处理就好了……

Code:

#include
using namespace std;
int pre[30000];
int a[30001];
int find(int x)
{
    if(pre[x]==x)
        return x;
    else
    {
        return find(pre[x]);
    }
}
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        if(n==0&&m==0)break;
        for(int i=0; i>k;
            for(int j=1; j<=k; j++)
                cin>>a[j];

            for(int jj=2; jj<=k; jj++)
            {
                if(find(a[jj])!=find(a[1]))
                {
                    int temp=find(a[jj]);
                    pre[temp]=a[1];
                }
            }
        }
    int total=0;
    for(int i=0; i

POJ1703   Find them, Catch them

题意:有两个帮派,各有一些成员,现在我们要区分它们的关系,在一个帮派,不在一个帮派或者不确定……

很容易想到并查集,但这道题目其实是一道种类并查集。我们不管要将所有的人放到一个中区,我们还需要记录每个点和find()(就是唯一的pre[x]==x的那个点,也就是文章中说的掌门)的关系,开了一个数组w,和他一个帮派记录0,不一个记录1。 种类并查集往往需要通过关系计算w,,w[b]=(w[x]+w[y]+1)%2;这个式子就是这道题的公式。

我们针对询问,两个x,y如果find(x)!=find(y)他们的关系还没有被确定。 反之比较w,如果w相等为一个帮派,反之为不同帮派的。


AC代码:

#include
#include
#include
using namespace std;
int pre[100001];
int w[100001];
int find(int x)
{
    int temp;
    if(pre[x]==x)return x;
    else
    {
        temp=pre[x];
        while(pre[temp]!=temp)
        {
            w[x]=(w[x]+w[temp])%2;
            temp=pre[temp];
        }
        pre[x]=temp;                            //路径压缩
    }
    return temp;
}
void Union(int x,int y)
{
    int a=find(x);
    int b=find(y);
    if(a!=b)
    {
        pre[b]=a;
        w[b]=(w[x]+w[y]+1)%2;
    }
}
int main()
{
    int T;
     scanf("%d",&T);
    while(T--)
    {
        memset(w,0,sizeof(w));
        int n,m,t1,t2;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            w[i]=0;
            pre[i]=i;
        }

        char c;
        for(int i=1; i<=m; i++)
        {    getchar();
            scanf("%c %d %d",&c,&t1,&t2);
            if(c=='A')
            {
                int x1=find(t1),x2=find(t2);
                if(x1!=x2)
                    printf("Not sure yet.\n");
                else
                {
                    if(w[t1]==w[t2])
                        printf("In the same gang.\n");
                    else
                        printf("In different gangs.\n");
                }
            }
            else
            {
                Union(t1,t2);
            }
        }
    }
}

POJ2524 Ubiquitous Religions

题目意思很简单,找不同宗教信仰……这题目没什么难度啦,大家练练手,不多说了。

AC code:

#include
#include
int pre[50001];
int rank[50001];
int num[50001];
int total;
using namespace std;
int find(int x)
{
    if(pre[x]==x)return x;
    else
        return find(pre[x]);
}
void Union(int x,int y)
{
    if(num[x]


POJ1182 食物链

非常经典的种类并查集。

和POJ1703很像,但是关键是有三种类型,公式可能比较难发现。思路还是把所有的不同类鱼放到一个关系中,在记录和首的关系……0同类,1吃他,2被吃。公式是关键。

Code:

#include
#include
using namespace std;
int pre[50001];
int rank[50001];
int sum;
int find(int x)
{    int temp;
    if(pre[x]==x)return x;
    else
    {
        temp=pre[x];
        while(pre[temp]!=temp)
        {
            rank[x]=(rank[x]+rank[temp])%3;
            temp=pre[temp];
        }
        pre[x]=temp;                            //路径压缩
    }
    return temp;
}
void Union(int x,int y,int c,int i)
{
    int a=find(x);
    int b=find(y);
    if(a==b)
    {
        if((rank[y]-rank[x]+3)%3!=c-1)
        {
            sum++;
        }
    }
    else
    {
        pre[b]=a;
        rank[b]=(rank[x]-rank[y]+3+c-1)%3;       //转化公式
    }
}
int main()
{
    int n,k;
    scanf("%d %d",&n,&k);
    sum=0;
    int a,b,c;
    for(int i=1; i<=n; i++)
    {
        pre[i]=i;
        rank[i]=0;
    }
    for(int i=1; i<=k; i++)
    {
        scanf("%d %d %d",&c,&a,&b);
        if(a>n||b>n)
        {
            sum++;
        }
        else if(a==b&&c==2)
        {
            sum++;
        }
        else
        {
            Union(a,b,c,i);
        }
    }
    printf("%d\n",sum);

}


你可能感兴趣的:(并查集)