codevs1074 洛谷2024 带权并查集

解题思路

已知A吃B,B吃C,C吃A。
所有有关系的动物在一个并查集里,但是这个并查集不简单,它是一个带权的并查集!
那么这个权值是什么呢?
设A与B在同一个集里,A到根节点X的权值(模3)为 Da ,B到根节点权值(模3)为 Db
如果 Da=2 ,则X吃A。
如果 Da=1 ,则A吃X。
如果 Da=0 ,则A与X为同一物种。
由此可以得到:
如果 Da=Db+1(mod3) ,则A吃B
如果 Da=Db1(mod3) ,则B吃A
如果 Da=Db(mod3) ,则A与B同类
那么路径压缩就可以解决此问题了(具体看代码)!
如果x和y不在同一个集里,那么就合并,否则查询是否满足条件。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
const int N=50005;
int n,m,ans;
int f[N],d[N];
int find(int x){
    if(f[x]==x)return x;
    int kl=f[x];
    f[x]=find(f[x]),d[x]=(d[x]+d[kl]+3)%3;//路径压缩d
    return f[x];
}
int main()
{
    int i,j,x,y,bj,r1,r2;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i)f[i]=i;
    for(i=1;i<=m;++i){
        scanf("%d%d%d",&bj,&x,&y);
        if(x>n||y>n){++ans;continue;}
        if(bj==2&&x==y){++ans;continue;}
        r1=find(x),r2=find(y);
        if(r1!=r2){
            f[r1]=r2;
            if(bj==2)d[r1]=(d[y]-d[x]+4)%3;//给新边d赋值
            else d[r1]=(d[y]-d[x]+3)%3;
        }
        else {
            if(bj==1&&d[x]%3!=d[y]%3)++ans;//检查是否相等
            else if(bj==2&&d[x]%3!=(d[y]+1)%3)++ans;
        }
    }
    printf("%d",ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值