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 性別相反,我們把這三個成為已經建立了關係的...