並查集 模版

2022-08-21 21:21:07 字數 3098 閱讀 7391

並查集

並查集,在一些有n個元素的集合應用問題中,我們通常是在開始時讓每個元素構成乙個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢乙個元素在哪個集合中。這一類問題近幾年來反覆出現在資訊學的國際國內賽題中,其特點是看似並不複雜,但資料量極大,若用正常的資料結構來描述的話,往往在空間上過大,計算機無法承受;即使在空間上勉強通過,執行的時間複雜度也極高,根本就不可能在比賽規定的執行時間(1~3秒)內計算出試題需要的結果,只能用並查集來描述。

並查集是一種樹型的資料結構,用於處理一些不相交集合的合併及查詢問題。常常在使用中以森林來表示。

例題:

輸入格式:

第一行包含兩個整數n、m,表示共有n個元素和m個操作。

接下來m行,每行包含三個整數zi、xi、yi

當zi=1時,將xi與yi所在的集合合併

當zi=2時,輸出xi與yi是否在同一集合內,是的話輸出y;否則話輸出n

輸出格式:

如上,對於每乙個zi=2的操作,都有一行輸出,每行包含乙個大寫字母,為y或者n

模版**:

#include#include

using

namespace

std;

int a1,a2,a3,f[200001

],n,m;

int getf(int

o) void make(int v, int

u) void find(int v,int

u) int

main()

return0;

}

主要應用型別:

1.團夥問題(搭橋問題,修路問題):求連通塊

2.最小生成樹(kruskal)

3.l最近公共祖先(lca)中的tarjan

並查集的合併過程:(路徑壓縮)

int  find(int

x)

因此,並查集在查詢是否在同一集合時十分快捷

if(fa[a]==fa[b])

與並查集相對的,可以有一種拆分集:

例題:

題目描述:

維護乙個資料結構支援下列兩個操作:

-刪除某條邊,表示為」d x」,即為刪除第x條邊

-查詢兩點是否屬於乙個集合,表示為」q a b」,即為查詢節點a與節點b是否在乙個集合內,若在同乙個集合內,輸出」yes」,否則輸出」no」(輸出不包括引號)

輸入:第一行包括三個正整數資料結構中節點的個數n,邊數m,運算元q

接下來的m行每行包括兩個正整數u,v,表示節點u與節點v在同乙個集合裡

再接下來的q行每行包括乙個格式如題描述操作

輸出:對於每乙個查詢,輸出包括一行,表示查詢結果,即如果兩點屬於同乙個集合輸出」yes」,否則輸出」no」。

實際上,將刪除操作存下來,反向就可以建立並查集,將答案倒序輸出即可

**:

#include#include

#include

#define cl(x,n) memset(x, n, sizeof(x))

#define ll long long

using

namespace

std;

const

int maxn=1e5+10

;int

n, m, q;

inta[maxn], b[maxn];

intu[maxn], v[maxn], f[maxn];

char

op[maxn];

bool

del_state[maxn];

int _find(int

x) void merge(int x, int

y) int

main()

case'q

': default : break

; }

}for(int i=1; i<=m; i++) if(!del_state[i]) merge(a[i], b[i]);

/*將沒被刪除的邊加入集合

*/int ans[maxn], cnt=0

;

for(int i=q; i>0; i--)

else

merge(a[u[i]], b[u[i]]);

}for(int i=cnt-1; i>=0; i--) printf(ans[i] ? "

yes\n

" : "

no\n

");/*

倒序輸出答案

*/return0;

}

如果有多種歸屬的情況,可以考慮建立多倍並查集

例題:

洛谷p2024 食物鏈

洛谷上 sooke (dalao)的講解很詳細,此處就不再多說(才不是我懶得寫了)這道題比較巧妙的地方在於判斷相關性,建議一做。

至於tarjan,這個演算法主要還是與lca有關,並查集只是中途用來判斷兩點是否在同一棵子樹,不過對並查集的利用還是很巧妙的

下面給出部分tarjan的模版**:

void work(int fa,int son) 

...return

;}

由於遞迴過程中,work(son, to) 比 f[to]=son先執行,因此可以看做這是在樹上自底向上將節點加入並查集

". . ." 部分可以是對深度或距離的更新查詢,但由於查詢順序不一定於答案順序相同(work(fa, son) 函式像先序遍歷),就需要先存再輸出,不過整個演算法的時間複雜度是十分優秀的(因為只查詢了一遍)

(最後好像水了點)

模版 並查集

什麼是並查集 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。為何使用inline inline是c 關鍵字,在函式宣告或定義中,函式返回型別前加上關鍵字inline,即可以把函式指定為內聯函式。這樣可以解決一些頻繁呼叫的函式大量消耗棧空間 棧記憶體...

演算法模版之並查集

簡介 並查集實質是一種樹形的資料結構,一般用於處理一些不相交集合的合併及查詢問題。在具體問題解決上,比如找公共祖先節點 檢查圖的連通性等等,用通俗點的語言來描述的話,例如乙個幫派 有點社會呀 a的大哥是b,b的大哥是c,c的大哥是d,此時a b c d互相是不認識的,假如發生了幫派爭鬥,b和d相遇了...

模版 並查集(及其加權)

並查集是經典的圖論演算法,用來維護點與集合的關係,也簡潔明瞭。給定 n nn 個點,有 m mm 次操作,每次操作輸入 pppa aab bb 若 p 1 p 1 p 1 則 合併 aaab bb 若 p 2 p 2 p 2 則 查詢 aaab bb 是否同屬乙個集合 並查集初始化 每個父親點 都 ...