1. 程式人生 > >【NOI2001】食物鏈

【NOI2001】食物鏈

turn 需要 ring namespace 並查集 urn span || space

一道“擴展域”並查集的題目,我們把每一個點拆分成三個域:同類、食物、天敵。

我們假設x的同類域為x,食物域為x+n,天敵域為x+n+n。假設x與y是同類,那麽說明x+n與y+n是同類,x+n+n與y+n+n是同類。

假設x吃y,那麽x+n與y是同類,x+n+n與y+n是同類,x與y+n+n是同類。

現在我們只需要判斷一句話與之前處理的關系是否沖突即可,如果不沖突,就按照上面的同類關系合並即可;沖突則統計答案。

技術分享圖片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4
using namespace std; 5 int n,m; 6 int f[50010*3]; 7 int find(int x) { 8 if(f[x]!=x) f[x]=find(f[x]); 9 return f[x]; 10 } 11 void add(int x,int y) { 12 f[find(x)]=find(y); 13 } 14 int main() { 15 cin>>n>>m; 16 for(int i=1;i<=n*3;i++) f[i]=i; 17 int
ans=0; 18 for(int i=1;i<=m;i++) { 19 int op,x,y; 20 cin>>op>>x>>y; 21 if(x>n||y>n) { 22 ans++; 23 continue ; 24 } 25 if(op==1) { 26 if(find(x)==find(y+n)||find(x)==find(y+n+n)) ans++;
27 else { 28 add(x,y); 29 add(x+n,y+n); 30 add(x+n+n,y+n+n); 31 } 32 } 33 else if(op==2) { 34 if(find(x)==find(y)||find(x)==find(y+n)) ans++; 35 else { 36 add(x,y+n+n); 37 add(x+n,y); 38 add(x+n+n,y+n); 39 } 40 } 41 } 42 cout<<ans<<endl; 43 return 0; 44 }
AC Code

【NOI2001】食物鏈