並查集總結


 

並查集

一、定義

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

集合定義方法: “代表元法”,即 每個集合選擇一個固定的元素,作為整個集合的“代表”

二、基本操作

 Find —— 查詢一個元素屬於哪一個集合

Merge —— 把兩個集合合並成一個大集合

代碼示例:

三、路徑壓縮與按秩合並

——並查集的 奇技淫巧

①路徑壓縮

Get時, 將訪問過的節點直接指向樹根。 均攤復雜度

代碼示例:

int find(int x) { return x == fa[x] ? fa[x] : fa[x] = find(fa[x]); }

  

按秩合並

“秩”:樹的深度(未路徑壓縮) / 集合大小 。均攤復雜度

將”秩“記錄在 “代表元素” , 合並時, 將“秩”較小的樹根 作為 “秩”較大的樹根的子節點。

代碼示例:

 
void unionn(int x, int y){//按大小合並
    int u=Get(x), v=Get(y);
    if(u != v) {
        if(size[u]<size[v]) f[u]=v, size[v]+=size[u];//按大小合並每次要更新大小 
        else f[v]=u, size[u]+=size[v];
    }
}

 

void unionn(int x, int y){//按深度合並
    int u=Get(x), v=Get(y);
    if(u != v) {
        if(high[u] < hige[v]) f[u] = v;
        else {
            f[v]=u;
            if(high[u]==high[v]) high[u]++;//按深度合並只有在兩樹高度相等的時候更新
        }
    }
}

注:

①同時采用 “路徑壓縮” 和 “按秩合並” 優化的並查集, 每次Get操作復雜度可進一步降低到

即為 阿克曼函數

②如果題目需要維護明確的父子關系而用到了按秩合並的話,是不能用路徑壓縮的。一旦用了路徑壓縮,會破壞樹的形態,原來的節點會直接壓縮到祖先上,這樣一來我們調用的時候父子關系發生了改變,造成了算法的錯誤。

③並查集能在一張無向圖中維護節點之間的連通性(實際上可以維護許多具有傳遞性的關系)。

④並查集能夠快速跳過無用集合

 

普通並查集:

P1955 [NOI2015]程序自動分析

UVA1316 Supermarket

邊帶權並查集:

P1196 [NOI2002]銀河英雄傳說

 

POJ 1733 Parity game

 

擴展域並查集:

P2024 [NOI2001]食物鏈

 

POJ 1733 Parity game


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM