並查集
並查集,在一些有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#includeusing
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(intx)
因此,並查集在查詢是否在同一集合時十分快捷
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 是否同屬乙個集合 並查集初始化 每個父親點 都 ...