『並查集』並查集模板


學習並查集前提須知

並查集支持合並查詢,針對於查詢某兩點是否在同一個內,或者將兩點之間連一條線。

算法內容

競賽需要用到的點

1、並查集多用於其他算法的過渡使用,不單獨考

2、並查集的思路會多次在以后出現,請理解並查集的每一步思路

並查集略講

並查集是一個很簡單的數據結構,其基本思路圍繞着一個就是根節點展開,若有兩點的根節點相同那么就肯定在一棵樹內,所以我們只需要維護一個點的父親節點就好了,然后每次詢問都查找根節點是否相同。

但這是一種最優的情況,若樹退化成鏈的話,很明顯,復雜度高了很多,那就和暴力相同,怎樣避免這種情況發生呢?我們上面說到,我們只需要判斷兩點和根節點的關系,那么我們只保留當前點的根節點關系不就好了?的確,這樣就能夠滿足我們的問題了,這樣的優化方式我們叫做路徑壓縮,且這樣就出現了圖論中的一種特殊圖 菊花圖,這種圖你以后會遇到,多用於你的算法,在這里這個不是重點,不再贅述。

那么根據上面的信息我們就可以開始寫代碼了

部分代碼展現

起始化

//#define fre yes

#include <cstdio>

const int N = 1000005;
int par[N], Rank[N]; //Rank表示的是秩優化

void init(int n) {
    for (int i = 0; i <= n; i++) {
        par[i] = i;
        Rank[i] = 1;
    }
}

int main() {
    static int n, m;
    ...
    init(n);
    ...
}

合並操作 + 路徑壓縮 + 秩優化

int find(int x) {
    if(x == par[x]) return x;
    else return par[x] = find(par[x]);
} //路徑壓縮(與返回父親節點)

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return ;
    
    if(Rank[x] <= Rank[y]) par[x] = y;
    else par[y] = x;
    if(Rank[x] == Rank[y]) Rank[x]++;
} //秩優化 與 合並操作

查詢操作

int find(int x) {
    if(x == par[x]) return x;
    else return par[x] = find(par[x]);
}

bool same(int x, int y) {
    return find(x) == find(y);
}

所有代碼

//#define fre yes

#include <cstdio>

const int N = 200005;
int par[N], Rank[N];

void init(int n) {
    for (int i = 0; i <= n; i++) {
        par[i] = i;
        Rank[i] = 1;
    }
}

int find(int x) {
    if(par[x] == x) return x;
    else return par[x] = find(par[x]);
}

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return ;

    if(Rank[x] <= Rank[y]) par[x] = y;
    else par[y] = x;
    if(Rank[x] == Rank[y]) Rank[x]++;
}

bool same(int x, int y) {
    return find(x) == find(y);
}

int main() {
    static int n, m;
    scanf("%d %d", &n, &m);
    init(n);
    for (int i = 1; i <= m; i++) {
        int k;
        scanf("%d", &k);
        if(k == 1) {
            int x, y;
            scanf("%d %d", &x, &y);
            unite(x, y);
        } else {
            int x, y;
            scanf("%d %d", &x, &y);
            if(same(x, y)) puts("Y");
            else puts("N");
        }
    } return 0;
}


免責聲明!

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



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