並查集小結

2022-09-21 13:12:08 字數 2280 閱讀 5783

並查集可用來解決一些元素分組的問題,管理一系列不相交的集合

原理 起初有1~n個元素,它們分別指向自己,父節點即為自己

當兩個元素要合併時,用其中乙個元素指向另外乙個fa[i] = j

代表 i 的父元素是 j 。

// 查詢根節點

int find(int x)

void merge(int i,int j)
// 一句話

int find(int x)

// 拆分

int find(int x)

}

一共有 n個數,編號是 1∼n,最開始每個數各自在乙個集合中。

現在要進行 m個操作,操作共有兩種:

m a b,將編號為 a和 b 的兩個數所在的集合合併,如果兩個數已經在同乙個集合中,則忽略這個操作;

q a b,詢問編號為 a和 b 的兩個數是否在同乙個集合中;

模板

#include using namespace std;

const int n = 100010;

int p[n];

int find(int x)

int main()

}return 0;

}

自己寫的

#includeusing namespace std;

const int n = 100010, m = 100010;

int fa[n];

// 查詢父節點,順便將路徑上的點都指向集合中的根節點

int find(int x)

// 合併

void merge(int i, int j)

// 查詢是否在同一集合

bool query(int i, int j)

int main() else if(op == 'q')

}return 0;

}

給定乙個包含 n個點(編號為1∼n)的無向圖,初始時圖中沒有邊。

現在要進行 m個操作,操作共有三種:

c a b,在點 a 和點 b 之間連一條邊,a 和 b 可能相等;

q1 a b,詢問點 a 和點 b 是否在同乙個連通塊中,a 和 b 可能相等;

q2 a,詢問點 aa 所在連通塊中點的數量;

本題主要是要記錄連通塊中點的數量,初始化乙個size陣列,當合併的時候更新根節點的size陣列就可以了。

自己寫的

#include #include using namespace std;

const int n = 100010;

int p[n], size[n];

int find(int x)

// 合併時同乙個集合不一定所有節點指向根節點,但查詢時,find函式路徑壓縮會讓乙個集合中元素都指向根節點。

void merge(int i, int j)

int main()

while (m -- )

}else if(op == "q1") else

}return 0;

}

模板

#include using namespace std;

const int n = 100010;

int n, m;

int p[n], cnt[n];

int find(int x)

int main()

while (m -- )

}else if (op == "q1")

else

}return 0;

}

普通的並查集僅僅記錄的是集合的關係,這個關係只是同乙個集合或不在同一集合。而帶權並查集,不僅記錄集合的關係,還記錄著集合內元素的關係(或者說元素連線線的權值)。

解決這類問題主要是要明確距離在題目中指的是什麼,

並查集小結

並查集一類的題目最近也做了許多,相對來說,還是比較容易理解和實現的。最早開始接觸並查集是在學習用kruskal求最小生成樹的時候,後來接觸的題目多了,發現並查集還有好多用途,比如典型的判環,區間問題等等。學習並查集的過程中我發現,並查集的路徑壓縮十分重要,有時候對於題目限定的條件,在路徑壓縮的過程中...

並查集小結

小做了一下並查集相關的題目。就從最基礎的開始吧。首先是並查集的介紹,非常好的一篇博文 其次就是一些習題了。首先是這道題目 poj1308 is it a tree?整道題就是需要你判斷給出乙個有向圖是不是一棵樹。這裡會使用到並查集來判環,算是並查集的基礎應用 也就是判斷元素是不是屬於乙個集合 然後是...

並查集小結

並查集一類的題目最近也做了許多,相對來說,還是比較容易理解和實現的。最早開始接觸並查集是在學習用kruskal求最小生成樹的時候,後來接觸的題目多了,發現並查集還有好多用途,比如典型的判環,區間問題等等。學習並查集的過程中我發現,並查集的路徑壓縮十分重要,有時候對於題目限定的條件,在路徑壓縮的過程中...