並查集及種類並查集

2021-10-24 23:51:10 字數 2931 閱讀 3583

b站

並查集

int

find_root

(int x)

return x;

}int

hebing

(int x,

int y)

return0;

}}

檢驗**

#include

using

namespace std;

const

int n=

100;

const

int m=

200;

int parent[n]

,deep[n]

;int n,m;

struct edge

e[n]

;int cnt,head[n]

;void

init()

cnt=0;

}void

add(

int x,

int y)

intfind_root

(int x)

return x;

}int

hebing

(int x,

int y)

return0;

}}intdisjoin()

return ans;

}int

main()

if(disjoin()

)cout<<

"存在環"

;else cout<<

"不存在環"

;return0;

}/*有環6 6

1 21 3

2 43 5

3 64 5

無環6 5

1 21 3

2 43 5

3 6*/

並查集能維護連通性、傳遞性,通俗地說,親戚的親戚是親戚。

然而當我們需要維護一些對立關係,比如 敵人的敵人是朋友 時,正常的並查集就很難滿足我們的需求。

這時,種類並查集就誕生了。

常見的做法是將原並查集擴大一倍規模,並劃分為兩個種類。

在同個種類的並查集中合併,和原始的並查集沒什麼區別,仍然表達他們是朋友這個含義。

考慮在不同種類的並查集中合併的意義,其實就表達 他們是敵人 這個含義了。

按照並查集美妙的 傳遞性,我們就能具體知道某兩個元素到底是 敵人 還是 朋友 了。

至於某個元素到底屬於兩個種類中的哪乙個,由於我們不清楚,因此兩個種類我們都試試。

具體實現,詳見 p1525 關押罪犯。

再來看本題,每個動物之間的關係就沒上面那麼簡單了。

對於動物 x 和 y,我們可能有 x 吃 y,x 與 y 同類,x 被 y 吃。

但由於關係還是明顯的,11倍大小、2 倍大小的並查集都不能滿足需求,3 倍大小不就行了!

類似上面,我們將並查集分為 33 個部分,每個部分代表著一種動物種類。

設我們有 n個動物,開了 3n 大小的種類並查集,其中 1 ∼n 的部分為 a群系,n + 1∼2n 的部分為 b 群系,2n + 1 ∼3n 的部分為 c 群系。

我們可以認為 aa表示中立者,b 表示生產者,c 表示消費者。此時關係明顯:a 吃 b,a 被 c 吃。

當然,我們也可以認為 b 是中立者,這樣 c 就成為了生產者,a 就表示消費者。(還有 11種情況不提及了)

聯想一下 2倍大小並查集的做法,不難列舉出:當 a 中的 x 與 b 中的 y 合併,有關係 x吃 y;當 c 中的 x 和 c 中的 y 合併,有關係 x 和 y 同類等等……

但仍然注意了!我們不知道某個動物屬於 a,b,還是 c,我們3 個種類都要試試!

也就是說,每當有 1 句真話時,我們需要合併 3 組元素。

容易忽略的是,題目中指出若 x 吃 y,y 吃z,應有 x 被 z 吃。

這個關係還能用種類並查集維護嗎?答案是可以的。

若將 x 看作屬於 a,則 y 屬於 b,z 屬於 c。最後,根據關係 aa 被 c 吃可得 x被 z 吃。

既然關係滿足上述傳遞性,我們就能放心地使用種類並查集來維護啦。

#include

int fa[

300005];

int n,k,ans;

inline

intread()

//讀入優化

intfind

(int x)

//查詢

intunity

(int x,

int y)

//合併

intmain()

// 不屬於該食物鏈顯然為假

if(z==1)

//如果1是2的天敵或獵物,顯然為謊言

unity

(x,y)

;unity

(x+n,y+n)

;unity

(x+2

*n,y+

2*n)

;//如果為真,那麼1的同類和2的同類,1的獵物是2的獵物,1的天敵是2的天敵

}else

if(z==2)

//其實是廢話但是可以稍微省點時間if(

find

(x)==

find

(y)||

find

(x+2

*n)==

find

(y))

//如果1是2的同類或獵物,顯然為謊言

unity

(x,y+

2*n)

;unity

(x+n,y)

;unity

(x+2

*n,y+n)

;//如果為真,那麼1的同類是2的天敵,1的獵物是2的同類,1的天敵是2的獵物}}

printf

("%d\n"

,ans)

;return0;

}

種類並查集

先來經典題目poj 1182 其實我現在都不是很明白這個題是怎麼做的 這道題貌似是並查集和向量做的,其中的關係推斷現在不是很明白。只知道和根節點的關係有三種,一種是同類 rank x 0 一種是被根節點吃掉 rank x 1 一種是吃掉根基點 rank x 2 如果不是很明白這道題的話可以跳過這道題...

種類並查集

食物鏈 poj 1182 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y...

種類並查集

種類並查集是我自己分的類,下面是幾道相關的題,都要求分類。a bug s life 核心思想 不難發現,一旦我們有了兩個bug之間的關係,我們一定可以判斷出它們的性別異同,甚至可以相互推斷,比如 a 與 b 能 b 與 c 能 那麼就能推出 a,c 與 b 性別相反,我們把這三個成為已經建立了關係的...