並查集 食物鏈

2021-08-14 02:25:58 字數 1699 閱讀 6132

題目描述

動物王國中有三類動物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 ...