POJ1182 食物链 关系并查集

POJ1182 食物链

/*关系并查集 kind[]
204MS   768K
*/
#include <stdio.h>
#include <string.h>
const int MAX=5*1e4+5;
int pa[MAX],kind[MAX];
void make_set(int N)//初始化节点
{
    for (int k=1;k<=N;k++)
    {
        pa[k]=k;
        kind[k]=0;
    }
}
int find_set(int x)//查找父节点路径压缩
{
    int tx,h=x,s1=0,s2;
    while (h!=pa[h])
    {
        s1+=kind[h];
        h=pa[h];
    }
    while (x!=pa[x])
    {
        tx=pa[x];
        pa[x]=h;
        s2=kind[x];
        kind[x]=s1%3;
        s1=s1-s2;
        x=tx;
    }
    return h;
}
int union_set(int x,int y,int k)//合并集合
{
    int tx=find_set(x);
    int ty=find_set(y);
    if (tx==ty)
    {
        if ((kind[x]-kind[y]+3)%3==k)//已有关系判断真假
            return 0;
        return 1;
    }
    pa[tx]=ty;
    kind[tx]=(3-kind[x]+kind[y]+k)%3;//状态转移
    return 0;
}
int main()
{
    int N,K,sum=0,D,X,Y;
    scanf ("%d%d",&N,&K);
    make_set(N);
    while (K--)
    {
        scanf ("%d%d%d",&D,&X,&Y);
        if (X>N||Y>N) sum++;
        else if (X==Y)
        {
            if (D==2)
                sum++;
        }
        else sum+=union_set(X,Y,D-1);
    }
    printf ("%d\n",sum);
    return 0;
}
//简单并查集模板
void make_set(int N)//初始化
{
    for (int k=0;k<=N;k++)
        pa[k]=k;
}
int find_set(int x)//寻找父亲节点并路径压缩
{
    int tx,h=x;
    while (h!=pa[h])
        h=pa[h];
    while (x!=pa[x])
    {
        tx=pa[x];
        pa[x]=h;
        x=tx;
    }
    return h;
}
void union_set(int x,int y)//合并集合
{
    x=find_set(x);
    y=find_set(y);
    if (x==y) return ;
    if (rand()&1) pa[x]=y;//打乱操作可不加
    else pa[y]=x;
}


猜你喜欢

转载自blog.csdn.net/nrtostp/article/details/80144504