C 並查集 例題講解

2021-09-27 03:09:36 字數 2451 閱讀 9639

一、基本性質 

1.在基於並查集的基礎上增加記錄陣列_rank,表示i與其同集合根節點的關係

二、例題講解 

2.1【食物鏈 poj - 1182】——vjudge題目鏈結

題意:動物王國中有三類動物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(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:

只有乙個整數,表示假話的數目。

sample input:

100 7

1 101 1 

2 1 2

2 2 3 

2 3 3 

1 1 3 

2 3 1 

1 5 5

sample output:31

題目分析: 

rank[x] = 0:表示x與f[x]為同種生物 

rank[x] = 1:表示x吃f[x] 

rank[x] = 2:表示x被f[x]吃

以下為accepted**

#include #include #include using namespace std;

const int n = 54014;

int f[n], _rank[n];

void init(int n);

int get_f(int x);

bool merge(int d, int x, int y);

int main()

if(d == 2 && x == y)

if(!merge(d, x, y))

}printf("%d\n", cnt);

return 0;

}void init(int n)

}int get_f(int x)

bool merge(int d, int x, int y)

else

}else

else

}}

2.2【por costel and the match gym - 100923h——vjudge題目鏈結】

題意:已知有n個戰士,分屬於兩個紅、藍陣營,現輸入m條敵對關係,當本條關係資訊與之前的真的關係資訊衝突,則認為本條關係資訊為假(即先輸入的敵對關係優先為真)

input:

第一行輸入t,代表t組測試資料 

每組測試資料第一行輸入整數n和m,表示n個戰士,m條敵對關係判斷語句 

之後輸入m行,每行含有整數x和y,表示認為x和y為敵對關係(即陣營不同)

output:

輸出m行,每行輸出」yes」或」no」(不含引號),表示判斷所得本條語句的真假

sample input:

13 3

1 22 3

1 3sample output:

yesyes

no題目分析: 

rank[x] = 0:表示x與f[x]為朋友(即屬於同一陣營) 

rank[x] = 1:表示x與f[x]為敵人(即分屬不同陣營)

以下為accepted**

#include #include #include using namespace std;

const int n = 104014;

int f[n], _rank[n];

void init(int n);

int get_f(int x);

bool merge(int x, int y);

int main()

}return 0;

}void init(int n)

}int get_f(int x)

bool merge(int x, int y)

else

return true;

}

2.2例題感悟:1.基於並查集;2.認真仔細尋找rank[i]表示含義

並查集例題

題目描述 假如已知有n個人和m對好友關係 存於集合r 如果兩個人是直接或間接的好友 好友的好友的好友 則認為他們屬於同乙個朋友圈。請寫程式求出這n個人裡一共有多少個朋友圈。輸入 輸入包含多個測試用例,每個測試用例的第一行包含兩個正整數 n m,1 n,m 100000。接下來有m行,每行分別輸入兩個...

並查集例題

找出根節點,如果只有乙個節點,根節點是自己 作迴圈,如果父節點不是自己,一直迴圈 public int find int x return x public void union int x,int y parent rootx rooty count 並查集自己的理解 剛開始每個節點都是看作單獨的...

並查集講解

所謂並查集,實際上可以認為是對集合的合併與查詢,所以下面從集合開始講解。假設有集合a 1 2 3 4 5,集合b 6 7 8 9 0 假設此時有乙個條件導致a中的隨便乙個數與b中的隨便乙個數在乙個集合內,那麼很顯然ab將會合併成乙個更大的集合。接下來考慮演算法 對乙個陣列f 50 來說,先對其進行初...