【luogu2024】 [NOI2001]食物链 [并查集]

P2024 [NOI2001]食物链 

从去年学并查集的时候就想做 emmmm奈何那时脑子不够用

开三倍x 自身 x+2n 猎物 x+3n 天敌

然后按照那个关系来判断关系 猎物的猎物为天敌 天敌的天敌为猎物

要注意的是判断完要把三种关系都给合并了 我就合并了一种emmmmmmm

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<stack>
#include<algorithm>
using namespace std;
#define ll long long
#define rg register
const int N=200000+5,pw=11,inf=0x3f3f3f3f,P=19650827;
int n,k,f[N],ans=0;
template <class t>void rd(t &x)
{
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void Union(int x,int y) {f[find(y)]=find(x);}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("nocows.out","w",stdout);
    rd(n),rd(k);
    for(rg int i=1;i<=n*3;++i) f[i]=i;
    while(k--){
        int op,x,y;
        rd(op),rd(x),rd(y);
        if(x>n||y>n) {++ans;continue;}
        if(op==1){
            if(find(x+n)==find(y)||find(x+2*n)==find(y)) ++ans;
            //为猎物 为天敌 
            else Union(x,y),Union(x+n,y+n),Union(x+2*n,y+2*n);
        }
        else{
            if(x==y) {++ans;continue;}
            if(find(x)==find(y)||find(x)==find(y+n)) ++ans;
            //为同类  为猎物
            else Union(x,y+2*n),Union(x+n,y),Union(x+2*n,y+n);
        }
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2019-06-11 17:54  委屈的咸鱼鱼鱼鱼  阅读(150)  评论(0编辑  收藏  举报