帶權並查集詳解

一、什麼是並查集

並查集(DisjointSet)是一種樹型的數據結構,用於處理一些不相交的集合(Disjoint Sets)。通常支持如下幾種操作:

  • 初始化
  • 查找元素所在集合
  • 合併兩個集合

class DisjointSet {
public:
    DisjointSet(int n) {
        for(int i=0; i<n; i++) {
            parent[i] = i;
        }
    }
    int Find(int x) {
        if(parent[x]==x) return x;
        return parent[x] = Find(parent[x]);
    }
    void Union(int x, int y) {
        int root_x = Find(x), root_y = Find(y);
        if(root_x!=root_y) parent[root_x] = root_y;
    }
private:
    int parent[MAX];
} ds(MAX);

二、帶權並查集的概念

帶權並查集(Weighted Disjoint Set)是在普通並查集的基礎上,每個集合還有一個權值的概念,用來表示這個集合中的元素之間的某種關係,例如長度等。

三、帶權並查集的變化

1. 表示元素之間的關係

在普通並查集中,集合中的元素之間沒有特定的關係,每個元素只有屬於哪個集合的信息。而在帶權並查集中,每個集合增加了一個權值,用於表示集合中元素之間的某種關係。

2. 查找最值

在帶權並查集中,由於集合中的元素之間存在關係,那麼可以在查找集合的同時,求出集合中權值的最大值或最小值。

3. 路徑壓縮時同時維護權值的信息

在路徑壓縮時,如果要將元素的父節點設為根節點,那麼根據路徑壓縮的方式,該節點的祖先節點權值可能會丟失。因此需要維護每個節點祖先節點的權值信息,以便查找時能夠找到根節點並計算正確的權值.


class WeightedDisjointSet {
public:
    WeightedDisjointSet(int n) {
        for(int i=0; i<n; i++) {
            parent[i] = i;
            rank[i] = 0;
            weight[i] = 0;
        }
    }
    int Find(int x) {
        if(parent[x]==x) return x;
        int root = Find(parent[x]);
        weight[x] += weight[parent[x]]; // 維護權值信息
        return parent[x] = root;
    }
    void Union(int x, int y, int w) {
        int root_x = Find(x), root_y = Find(y);
        if(root_x!=root_y) {
            if(rank[root_x]>rank[root_y]) {
                parent[root_y] = root_x;
                weight[root_y] = w - weight[y] + weight[x]; // 更新權值
            } else {
                parent[root_x] = root_y;
                weight[root_x] = -w + weight[y] - weight[x]; // 更新權值
                if(rank[root_x]==rank[root_y]) rank[root_y]++;
            }
        }
    }
private:
    int parent[MAX], rank[MAX], weight[MAX];
} wds(MAX);

四、帶權並查集的應用

1. Kruskal算法

Kruskal算法是一種用於求帶權圖的最小生成樹(Minimum Spanning Tree)的算法。具體思路是將邊按照權值從小到大排序,然後依次考慮每條邊,如果這條邊的兩個端點不在同一個集合中,則將它們所在的集合合併,並將這條邊加入到最小生成樹的邊集中。


struct Edge {
    int u, v, w;
    bool operator<(const Edge& e) const {
        return w < e.w;
    }
};
vector<Edge> edges; // 存儲邊的集合
int kruskal(int n) {
    sort(edges.begin(), edges.end());
    WeightedDisjointSet wds(n);
    int ans = 0;
    for(int i=0; i<edges.size(); i++) {
        Edge& e = edges[i];
        if(wds.Find(e.u)!=wds.Find(e.v)) {
            wds.Union(e.u, e.v, e.w);
            ans += e.w;
        }
    }
    return ans;
}

2. 求連通塊大小

可以利用帶權並查集的合併操作求出連通塊的大小。


int cnt = 0;
for(int i=0; i<n; i++) {
    if(wds.Find(i)==i) {
        cnt++;
    }
}

3. 求連通塊中的最大最小值

可以在查找集合的同時,維護最大最小值。


int Find(int x) {
    if(parent[x]==x) return x;
    int root = Find(parent[x]);
    max_val[x] = max(max_val[x], max_val[parent[x]]);
    min_val[x] = min(min_val[x], min_val[parent[x]]);
    return parent[x] = root;
}

原創文章,作者:ZCTWI,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/334920.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
ZCTWI的頭像ZCTWI
上一篇 2025-02-05 13:05
下一篇 2025-02-05 13:05

相關推薦

  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和算法 C語言貪吃蛇主要運用了以下數據結構和算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25

發表回復

登錄後才能評論