並查集,在一些有n個元素的集合應用問題中,我們通常是在開始時讓每個元素構成乙個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢乙個元素在哪個集合中。這一類問題近幾年來反覆出現在資訊學的國際國內賽題中,其特點是看似並不複雜,但資料量極大,若用正常的資料結構來描述的話,往往在空間上過大,計算機無法承受;即使在空間上勉強通過,執行的時間複雜度也極高,根本就不可能在比賽規定的執行時間(1~3秒)內計算出試題需要的結果,只能用並查集來描述。
並查集是一種樹型的資料結構,用於處理一些不相交集合(disjoint sets)的合併及查詢問題。常常在使用中以森林來表示。
摘自網路↑
下面主要是自己的感悟emm可能有些不對的地方歡迎指出
並查集,顧名思義,方便的主要就是合併和查詢兩種基本操作,然後說一下並查集的基本操作:
fa[i]表示點i的父節點,根節點的父節點是它自己。
這裡就涉及到初始化,因為開始的時候每乙個點都是一棵獨立的樹,它們都是根節點,所以它們要把fa[i]=i。
另外sz[i]表示這一棵樹的深度,只有根節點的sz值才是有效的,可能有些題目裡不會涉及但是還是打上來哈
void init()
}
合併:
在實現合併操作之前, 我們先要想乙個問題:合併兩棵樹,是不是把這兩棵樹上任意兩個節點產生聯絡就可以了?
很明顯不是。
我們的合併操作,應該是要把其中一整棵樹都掛在另一棵樹的根節點上,也就是把a樹的根節點的父節點設定為b樹的根節點,就完成了a,b兩樹的合併。
所以現在的問題是取根節點。
初始寫法:
int get(int x)
但是!如果這麼寫,每次查詢根節點都要花費太多的時間,如果題目特殊構造一條鏈型的樹,那麼就會出現tle.
怎麼優化呢?
其實,在每次查詢根節點所途徑的路上遇到的所有節點,我們都可以把它們直接掛到根節點上,這樣下次查詢的時候就會方便許多了。
最終寫法:
int get(int x)
那麼接下來才是實現合併的操作。
所謂合併,就是如上所述,把其中一棵樹的根節點掛到另一棵樹的根節點上,實現合併,那麼就很容易實現:
void merge(int x,int y)
bool ask(int x,int y)
下面貼上完整**:
#includeusing namespace std;
int n,fa[10001],z,x,y,m,sz[10001];
void init()
}int get(int x)
void merge(int x,int y)
bool ask(int x,int y)
int main()
else
if(ask(x,y))cout<<"y" 並查集,顧名思義,合併 查詢 集合 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。對於概念等等的這裡不再贅述,直接講解應用。應用1 判斷圖中有多少聯通分量 或者圖是否聯通 聯通分量 1 hdu 1213 應用2 判斷圖是否... time limit 1000ms memory limit 65536k 某城市有n個人,現在給定關於n個人的m條資訊,m條資訊是兩個人在同乙個小區,根據所給資訊,判斷這個城市最多可能有多少個小區。n個人編號為1 n。多組輸入。每組第一行有兩個整數n,m 2 n 50000,0 m n 2 接下來... 一 基本概念 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。集就是讓每個元素構成乙個單元素的集合,也就是按一定順序將屬於同一組的元素所在的集合合併。在一些有n個元素的集合應用問題中,通常是在開始時讓每個元素構成乙個單元素的...資料結構 並查集
資料結構 並查集
資料結構 並查集