食物鏈(經典種類並查集問題) 詳解

2021-09-27 19:13:10 字數 2017 閱讀 7856

動物王國中有三類動物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是同類。第二種說法...