105 lines
3.6 KiB
Text
105 lines
3.6 KiB
Text
---
|
|
id: dsu
|
|
title: "Disjoint Set Union"
|
|
author: Benjamin Qi, Michael Cao
|
|
prerequisites:
|
|
- dfs
|
|
description: "The Disjoint Set Union (DSU) data structure allows you to add edges to an initially empty graph and test whether two vertices of the graph are connected."
|
|
frequency: 3
|
|
---
|
|
|
|
import { Problem } from "../models";
|
|
|
|
export const metadata = {
|
|
problems: {
|
|
sample: [
|
|
new Problem("YS", "Union Find", "unionfind", "Intro|Easy", false, []),
|
|
],
|
|
general: [
|
|
new Problem("Gold", "Closing the Farm", "646", "Easy", false, [], "Simulate process in reverse and maintain the # of connected components. Similar to [CSES Network Breakdown](https://cses.fi/problemset/task/1677)"),
|
|
new Problem("Gold", "Mootube", "789", "Normal", false, [], "Answer queries in decreasing order of $k$. Maintain size of each connected component. Same as [CSES Road Construction](https://cses.fi/problemset/task/1676)"),
|
|
new Problem("Gold", "Favorite Colors", "1042", "Very Hard", false, ["DSU"], "Small to large merging is mentioned in the editorial, but we were unable to break solutions that just merged naively. Alternatively, just merge linked lists in $O(1)$ time."),
|
|
],
|
|
}
|
|
};
|
|
|
|
<Problems problems={metadata.problems.sample} />
|
|
|
|
## Resources
|
|
|
|
<Resources>
|
|
<Resource source="CSA" title="Disjoint Data Sets" url="disjoint_data_sets" starred>both optimizations, diagrams</Resource>
|
|
<Resource source="PAPS" title="11.1 - Disjoint Sets" starred>both optimizations, no diagrams</Resource>
|
|
<Resource source="CPH" title="15.2 - Union-Find">small to large, diagrams</Resource>
|
|
<Resource source="IUSACO" title="10.6 - Disjoint-Set Data Structure">path compression, diagrams</Resource>
|
|
<Resource source="TC" title="Disjoint Set Data Structures" url="disjoint-set-data-structures">diagrams</Resource>
|
|
<Resource source="CPC" title="3 - Data Structures" url="03_data_structures"></Resource>
|
|
</Resources>
|
|
|
|
Note: You may prefer to use this in place of DFS for computing connected components.
|
|
|
|
<Optional title="DSU Complexity Proofs">
|
|
|
|
- [$\log^* n$](https://en.wikipedia.org/wiki/Proof_of_O(log*n)\_time_complexity\_of_union%E2%80%93find)
|
|
- [$\alpha (m,n)$](https://dl.acm.org/doi/pdf/10.1145/321879.321884)
|
|
|
|
</Optional>
|
|
|
|
## Implementations
|
|
|
|
<LanguageSection>
|
|
|
|
<CPPSection>
|
|
|
|
Check PAPS for the explanation. `e[x]` contains the negation of the size of $x$'s component if $x$ is the representative of its component, and the parent of $x$ otherwise.
|
|
|
|
<resource source="Benq (from KACTL)" url="https://github.com/bqi343/USACO/blob/master/Implementations/content/graphs%20(12)/DSU/DSU%20(7.6).h"> </resource>
|
|
|
|
```cpp
|
|
struct DSU {
|
|
vi e; void init(int N) { e = vi(N,-1); }
|
|
// get representive component, uses path compression
|
|
int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); }
|
|
bool sameSet(int a, int b) { return get(a) == get(b); }
|
|
int size(int x) { return -e[get(x)]; }
|
|
bool unite(int x, int y) { // union by size
|
|
x = get(x), y = get(y); if (x == y) return 0;
|
|
if (e[x] > e[y]) swap(x,y);
|
|
e[x] += e[y]; e[y] = x; return 1;
|
|
}
|
|
};
|
|
```
|
|
|
|
</CPPSection>
|
|
|
|
<JavaSection>
|
|
|
|
This implementation assumes that `p` is an array that starts such that `p[i] = i` for every $0 <= i <= n$. It uses path compression only.
|
|
|
|
```java
|
|
//finds the "representative" node in a's component
|
|
int find(int a) {
|
|
if (p[a] == a)
|
|
return a;
|
|
else
|
|
return p[a] = find(p[a]);
|
|
}
|
|
|
|
//returns whether the merge changed connectivity
|
|
boolean merge(int a, int b) {
|
|
int A = find(a);
|
|
int B = find(b);
|
|
if (A == B)
|
|
return false;
|
|
p[a] = p[b] = p[A] = p[B];
|
|
return true;
|
|
}
|
|
```
|
|
|
|
</JavaSection>
|
|
|
|
</LanguageSection>
|
|
|
|
## Problems
|
|
|
|
<Problems problems={metadata.problems.general} />
|