概述
並查集主要是解決以下幾種問題的:
- 各節點之間的關係
- 某節點和它祖先之間的關係
種類
- 樸素並查集,一個集合的資訊可以儲存在它的祖先節點上。
- 帶權並查集,維護的是某節點與它祖先的關係。
- 擴充套件域並查集(種類並查集),本質是多開幾倍空間的樸素並查集,維護的是各個陣營之間的關係,且幾個域裡具有對稱性。形式化而言,可以把每個域看作一個平行時空,當朋友域裡的我和朋友域裡的他是朋友時,我和他是朋友;當朋友域裡的我和敵人域裡的他是朋友時,我和他是敵人。
模板
樸素並查集模板
點選檢視程式碼
int findf(int x)
{
if(f[x]!=x)f[x]=findf(f[x]);
return f[x];
}
帶權並查集模板
點選檢視程式碼
int findf(int x)
{
if(f[x]==x)return x;
int orif=f[x];
f[x]=findf(f[x]);
dis[x]+=dis[orif];
return f[x];
}
種類並查集模板
樸素並查集上多開幾倍空間。
求最大連通塊點數
樸素並查集,把該連通塊資訊算在祖先節點上,combine 時就傳遞祖先節點的資訊。
求連通塊數量
祖先節點的個數就是連通塊數量,因此遍歷每一個點,如果 findf(i)==i
則 num++
。
套路
- 幾個點之間可以任意交換,則他們是一個集合,常用於序列上的並查集問題。交換
- 帶權並查集的權值取模,可以當成種類並查集來用。食物鏈
- 建立虛點,來實現兩個集合合併時,不影響兩個集合原來各自的操作,且後續共享操作的功能。網路分析
- 破壞兩個節點間的關係,反向合併集合,從最後一次破壞開始,往前合併破壞的節點。星球大戰
- 判斷兩種說法是否矛盾,把相同的說法加入同一個並查集裡;可以在一開始時就判斷矛盾,也可以在最後才判斷。程式自動分析
- 判斷圖的連通性,如 Kruskal 演算法。
- 最少的任意位置的交換次數,把要交換的東西合併成一個集合,交換次數即為 \(size-1\) 。情侶牽手
- 判斷是否有環的存在。
- 超級源點,這個超級源點既可以看作是把整個集合賦某個特定的值,也可以看作是給一些滿足要求的節點連邊。三值邏輯,被圍繞的區域