luogu2024 食物链 (并查集)

把一个点拆成三个,分别对应它的同类、它的猎物和它的天敌,这样的话(以下的相等都是并查集意义上的):

如果令a,b同类,那么a的猎物不能是b的同类,a的天敌不能是b的同类

如果令a吃b,那么a的同类不能是b的同类、a的天敌不能是b的同类。

要令a,b同类,就使(a和b)的同类、猎物、天敌分别相等

要令a吃b,就使a的猎物是b的同类,b的天敌是a的同类,a的天敌是b的猎物(题目中要求A吃B,B吃C,C吃A)

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define ll long long
 4 using namespace std;
 5 const int maxn=50050;
 6 
 7 inline ll rd(){
 8     ll x=0;char c=getchar();int neg=1;
 9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
11     return x*neg;
12 }
13 
14 int N,K,fa[maxn*3];
15 
16 int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
17 void add(int a,int b){
18     fa[getfa(a)]=getfa(b);
19 }
20 
21 int main(){
22     //freopen("testdata.in","r",stdin);
23     int i,j,k,ans=0;
24     N=rd();K=rd();
25     for(i=1;i<=N*3;i++) fa[i]=i;
26     for(i=1;i<=K;i++){
27         int a=rd(),b=rd(),c=rd();
28         if(b>N||c>N) {++ans;continue;}
29         if(a==1){
30             if(getfa(b)==getfa(c+N)||getfa(b)==getfa(c+2*N)){++ans;continue;}
31             add(b,c);add(b+N,c+N);add(b+2*N,c+2*N);
32         }else{
33             if(getfa(b)==getfa(c)||getfa(b+2*N)==getfa(c)){++ans;continue;}
34             add(b+N,c);add(b,c+2*N);add(b+2*N,c+N);
35         }
36     }
37     printf("%d\n",ans);
38     return 0;
39 }

 

posted @ 2018-09-13 22:47  Ressed  阅读(168)  评论(0编辑  收藏  举报