題目描述
動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b, b吃c,c吃a。
現有n個動物,以1-n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。
有人用兩種說法對這n個動物所構成的食物鏈關係進行描述:
第一種說法是「1 x y」,表示x和y是同類。
第二種說法是「2 x y」,表示x吃y。
此人對n個動物,用上述兩種說法,一句接一句地說出k句話,這k句話有的是真的,有的是假的。當一句話滿足下列三條之一時,這句話就是假話,否則就是真話。
1) 當前的話與前面的某些真的話衝突,就是假話;
2) 當前的話中x或y比n大,就是假話;
3) 當前的話表示x吃x,就是假話。
你的任務是根據給定的n(1<=n<=50,000)和k句話(0<=k<=100,000),輸出假話的總數。
input
第一行是兩個整數n和k,以乙個空格分隔。
以下k行每行是三個正整數 d,x,y,兩數之間用乙個空格隔開,其中d表示說法的種類。
若d=1,則表示x和y是同類。
若d=2,則表示x吃y。
output
只有乙個整數,表示假話的數目。
分析
這題這種同類判斷的很明顯看出來是並查集,但是有個問題,那就是怎麼判斷誰吃誰?
同時感謝洛谷的題解
經過學習以後,我知道這個可以用建立補集法來做
首先生成三個集合abc
然後abc的關係就是a吃b,b吃c,c吃a(這點不用在程式中定義,只是判斷的時候要注意好)
接著如果輸入合併的時候,就把同個集合的兩個點連邊(a連a,以此類推)
如果輸入黑吃黑食用關係時,就把定義互吃的集合連邊(a連b,以此類推)
那麼怎麼判斷錯誤呢?
合併時,只要判斷x能否吃y和y能否吃x就行了
食用時,只要判斷x和y是否在同一集合內連邊還有y能否吃x就行了
溫馨提醒,三個集合共用乙個陣列會容易理解
a集合中的i元素表示為f[i]
b集合中的i元素表示為f[i+n]
c集合中的i元素表示為f[i+2*n]
應該很詳細了吧?如果不夠詳細,可以去洛谷的帶**的題解區看哦:
#include
#include
using namespace std;
int f[150001];
int n,k,ans;
int i,m,x,y;
int fin(int a)
return root;
}void uni(int a,int b)
int main()
if (m==1)
if (fin(y)==fin(x+n))
uni(x,y);
uni(x+n,y+n);
uni(x+2
*n,y+2
*n);
}else
if (fin(y)==fin(x+n))
uni(x,y+n);
uni(x+n,y+2
*n);
uni(x+2
*n,y);}}
printf("%d",ans);
}
並查集 食物鏈
noi2001,水題,但是我調了很久。食物鏈time limit 1000ms memory limit 10000k total submissions 27766 accepted 8066 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃...
並查集 食物鏈
食物鏈 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示...
並查集 食物鏈
動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是同類。第二種說法是 2 ...