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_(int N)//初始化
{
    for (int k=0;k<=N;k++)
        pa[k]=k;
}
int find_(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;
}
int find_(int x)//递归版本
{
    if(x!=pa[x]) pa[x]=find_(pa[x]);
    return pa[x];
}
void union_(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;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值