[leetcode] 並查集(Ⅰ)
阿新 • • 發佈:2020-04-27
## 預備知識
並查集 (Union Set) 一種常見的應用是計算一個圖中連通分量的個數。比如:
```text
a e
/ \ |
b c f
| |
d g
```
上圖的連通分量的個數為 2 。
並查集的主要思想是在每個連通分量的集合中,選取一個代表,作為這個連通分量的根。根的選取是任意的,因為連通分量集合中每個元素都是等價的。我們只需關心根的個數(也是連通分量的個數)。例如:
``` text
a e
/ | \ / \
b c d f g
```
也就是說:`root[b] = root[c] = root[d] = a` 而 `root[a] = -1`(根節點的特徵也可以定義為 `root[x] = x`)。
最後計算 `root[x] == -1` 的個數即可,這也就是連通分量的個數。虛擬碼如下:
```cpp
// n nodes, all nodes is independent at the beginning
vector root(n, -1);
int find(int x)
{
return root[x] == -1 ? x : (root[x] = find(root[x]));
}
// if x and y are connected, then call union(x, y)
void unionSet(int x, int y)
{
x = find(x), y = find(y);
if (x != y) root[x] = y; // it also can be root[y] = x
}
int main()
{
// (x,y) are connected
while (cin >> x >> y)
unionSet(x, y);
// print the number of connectivity components
print(count(root.begin(), root.end(), -1));
}
```
`find` 函式也可以通過迭代實現:
```cpp
int find(int x)
{
int t = -1, p = x;
while (root[p] != -1) p = root[p];
while (x != p) {t = root[x]; root[x] = p; x = t;}
return p;
}
```
## 朋友圈
題目[547]:點選 [