動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。
a**, 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和k句話,輸出假話的總數。
輸入格式
第一行是兩個整數n和k,以乙個空格分隔。
以下k行每行是三個正整數 d,x,y,兩數之間用乙個空格隔開,其中d表示說法的種類。
若d=1,則表示x和y是同類。
若d=2,則表示x吃y。
輸出格式
只有乙個整數,表示假話的數目。
資料範圍
1≤n≤50000,
0≤k≤100000
輸入樣例:
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
輸出樣例:
3去年就做過這個很經典的題,但那時候沒有真正理解,現在再來整理吧~
思路:我們要判斷每次給出的資訊是否是假話必須判斷他們之間的關係,但是儲存兩兩之間的關係顯然是不現實的,那麼我們可儲存每個數與根節點的關係。
即我們可以把這些關係看成一棵樹,距離根節點為1的就是可以吃根節點的,為2的就是可以可以吃第1層的,為3的和根節點是同類(3可以吃2, 1->2 , 2-> 3 那麼一定存在 3->1,所以為3的一定是被1吃的,而根節點也是被1吃的,那麼根節點和3是同類),那麼以此類推,我們可以發現,以3為迴圈,只要知道距離,我們就可以找出每個點與根節點的關係。
還有乙個問題是:距離是什麼?每次我們發現有兩個動物x,y, 他們存在x->y (y可以吃x)的關係的時候,x和y就產生了一條距離為1的邊。但是由於我們的樹太深了會導致超時,我們需要壓縮路徑,這時候就要處理好每個節點和根節點的距離。
首先,路徑壓縮的時候,我們正常的寫法是:
int find
(int x)
由於我們多儲存了乙個變數,即與根節點之間的距離,所以我們在壓縮路徑的時候要把距離也更新一下。
假如我們壓縮路徑的時候是這樣的,那麼此時d[x]代表到他的父節點的距離,壓縮完以後父節點變成了根節點,那麼我們讓d[x]加上父節點到根節點的距離即可。
int find
(int x)
return pre[x]
;}
還有就是我們合併的時候,也要處理好距離,具體的看**注釋。**:
#include
#include
#include
using namespace std;
const int n
=5e4+10
;int pre[n]
,d[n];
int find
(int x)
//查詢根節點+路徑壓縮
return pre[x];}
int main()
}else
if(t==2)
//x吃y的關係
}}cout<
return0;
}
POJ食物鏈(經典種類並查集)
食物鏈 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是同類。第二種說法...
食物鏈 種類並查集
推薦blog傳送門,超級詳細 做題思路 種類並查集,首先利用乙個陣列a來確定並查集關係,同時在建立乙個陣列b來表示某點與他們的boss點 根點 的關係。現規定 0 某點與他的根點為同類 1 某點與他的根點的關係為,根點種類的動物的可以吃掉該點種類的動物 2 某點與他的根點的關係為,該點種類的動物的可...
食物鏈(種類並查集)
食物鏈 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是同類。第二種說法...