洛谷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 
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);
}

你可能感兴趣的:(洛谷luogu-2024 食物链 HQG_AC的博客)