洛谷luogu-2024 食物链 HQG_AC的博客

这题还是有点难度的。

题目意思:

有n个点,每两个点之间有相应的关系,读入若干条关系,求出不符合的关系数量。

解法:带权并查集
我们用0,1,2表示x和y的关系,0表示同类,1表示x吃y(吃),2表示y吃x(被吃)
如果我们知道了x和y的关系,y和z的关系,那我们就可以通过相加%3知道x和z的关系。
如:
x y =1 (x吃y)
y z =2 (z吃y)
x z =(1+2)%3=0   (x和z是同类)

所以我们在用并查集的时候对于每一条连向父亲的边都保存该边的权值即可。

详见代码:

#include<bits/stdc++.h> 
using namespace std;
int n,k,t,x,y,dad[100010],h[100010],X,Y,ans;
int find(int x){
    if(!dad[x])return x;
    int X=find(dad[x]);
    //h[x]表示x和dad[x]的关系
    //h[dad[x]]表示dad[x]和X的关系
    //要把h[x]变成x和X的关系 
    h[x]=(h[x]+h[dad[x]])%3;
    return dad[x]=X;
}
bool merge(int x,int y,int t){
    if(x>n||y>n)return 1;
    X=find(x);
    t-=h[x];
    Y=find(y);
    t+=h[y];
    t=(t+3)%3;
    if(X==Y)return t!=0;
    dad[X]=Y;
    h[X]=t;
    return 0;
}
int main(){
    scanf("%d%d",&n,&k);
    while(k--){
        scanf("%d%d%d",&t,&x,&y);
        ans+=merge(x,y,t-1);
    }
    printf("%d\n",ans);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值