JSK 习题:找出所有谎言(poj 1182)-并查集+偏移向量

本文介绍了一种使用带权并查集处理复杂关系推理的方法,通过定义三种基本关系(等于、吃、被吃),利用偏移向量表示不同关系间的转换,实现了高效的关系判断和更新。代码示例展示了如何初始化并查集、查找根节点以及合并两个集合的过程。

在这里插入图片描述

思路:

利用带权并查集,用偏移向量表示三种关系,以此计算
利用向量表示关系,常设关系如,x对于y(x->y)的关系:
x等于y 为0
x吃y 为1
x被吃y 为2

由此可推出各种关系
fa[x]对于x的关系:3-r[x]
x对于fa[fa[x]]的关系:r[x]=(r[x]+r[fa[x]])%3
在这里插入图片描述
y对于x的关系:(3-r[x]+r[y])%3
y对于fx的关系:(d-1+r[x])%3
在这里插入图片描述
fy对于fx的关系:((d-1+r[x])%3)+3-r[y])%3

详解:http://blog.youkuaiyun.com/c0de4fun/article/details/7318642/
注:输入量过大应用scanf进行输入

代码:

#include <iostream>
using namespace std;
const int N=50010;
int ans=0;
int fa[N],r[N];
void init(int n)    //初始化
{
   for(int i=0;i<=n;i++)
    {
        fa[i]=i;
        r[i]=0;
    }
}
int find(int x)
{
    int fx=x;
    if(fa[x]==x)
        return x;
    else
    {
        fx=find(fa[x]);
        r[x]=(r[x]+r[fa[x]])%3;
        fa[x]=fx;
    }
    return fa[x];
}
int unite(int x,int y,int d)
{
     int fx=find(x);
     int fy=find(y);
     if(fx==fy)
     {
         if((3-r[x]+r[y])%3==d-1)
            return 1;
         else
            return 0;
     }
     else
     {
         r[fy]=((d-1+r[x])%3+3-r[y])%3;
         fa[fy]=fx;
         return 1;
     }
}

int main()
{
    int n,k;
    cin>>n>>k;
    init(n);
    for(int i=0;i<k;i++)
    {
        int d,x,y;
        cin>>d>>x>>y;
        if(x>n || y>n || (d==2 && x==y))
            ans++;
        else
        {
            if(!unite(x,y,d))
                ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ogmx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值