题解 并查集 POJ 1182

题意:三类动物ABCABBCCA
给出K句话来描述N个动物(各属于ABC三类之一)之间的关系,格式及意义如 下:
1X Y:表示XY是同类;
2X Y:表示XY
K句话中有真话有假话,当一句话满足下列三条之一时,这句话就是假话,否则就是 真话。
1)当前的话与前面的某些真的话冲突,就是假话;
2)当前的话中XYN大,就是假话;
3)当前的话表示XX,就是假话。
求假话的总数。
做法:由于对每个动物的种类未知,我们用3个堆来表示一个动物,即一个动物可以由 三种形态,A,B,C;如果两个动物为同类,我们就把这两个动物的3个堆合并。如果 x吃y,我们就将x-a,y-b;x-b,y-c;x-c,y-a合并。其中1个动物的堆用x,x+n,x+2n 表示。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int MAX=50000;
int par[3*MAX+50];


int Find(int a)
{
    if(par[a]!=a)
    par[a]=Find(par[a]);
    return par[a];
}
bool same(int x,int y)
{
    return Find(x)==Find(y);
}
void merge(int a,int b)
{
    int p1=Find(a);
    int p2=Find(b);
    if(p1==p2)
    return ;
    par[p2]=p1;
}
int main()
{
    int n,m,ans=0;
    int a,b,c,i;
    scanf("%d%d",&n,&m);
    for(i=0;i<=3*n;i++)
        par[i]=i;
    for(i=0;i<m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        b=b-1;c=c-1;
        if(b>=n||c>=n||b<0||c<0){ans++;continue;}
        if(a==1)
        {
            if(same(b,c+n)||same(b,c+2*n))
                ans++;
            else
                merge(b,c),merge(b+n,c+n),merge(b+2*n,c+2*n);
        }
        else if(a==2)
        {
            if(same(b,c)||same(c,b+n))
                ans++;
            else
                merge(b,c+n),merge(b+n,c+2*n),merge(b+2*n,c);
        }
    }
    printf("%d\n",ans);
    return 0;
}

posted on 2014-07-24 15:17  一锅土豆  阅读(99)  评论(0编辑  收藏  举报