Middle · Algorithms
Union-find: connectivity without repeated graph searches
How do you answer many connectivity queries while undirected edges are added?
Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.
ALGORITHM LAB · STEP THROUGH THE INVARIANT
n=5, edges=[(0, 1), (1, 2), (3, 4)]
Separate components
Each vertex initially owns its own root.
Computed traces for these inputs. Indexes identify cell positions; active cells are labeled as well as highlighted. Compare a boundary case using the scenario selector. No code is sent to a server.
type DisjointSet struct {
parent, size []int
Components int
}
// Caller supplies a nonnegative n and valid IDs to Find and Union.
func NewDisjointSet(n int) *DisjointSet {
d := &DisjointSet{parent: make([]int, n), size: make([]int, n), Components: n}
for i := range d.parent {
d.parent[i] = i
d.size[i] = 1
}
return d
}
func (d *DisjointSet) Find(x int) int {
for x != d.parent[x] {
d.parent[x] = d.parent[d.parent[x]]
x = d.parent[x]
}
return x
}
func (d *DisjointSet) Union(a, b int) bool {
a, b = d.Find(a), d.Find(b)
if a == b {
return false
}
if d.size[a] < d.size[b] {
a, b = b, a
}
d.parent[b] = a
d.size[a] += d.size[b]
d.Components--
return true
}Reveal a strong answer
A disjoint-set structure represents each component by a root. Find follows parent links; Union joins roots only when they differ. Joining by size keeps trees shallow, while path compression shortens future searches.
An attempted union of vertices already in one component must not decrement the component count. This supports dynamic connectivity as edges are added and cycle checks for undirected graphs; it does not produce shortest paths.
Ordinary union-find does not support arbitrary edge deletion. It mutates internal state even during compressed Find, so shared concurrent use needs synchronization. Validate vertex IDs and define behavior for an empty structure.
Common trap
Comparing immediate parents rather than roots, or decrementing the component count for a redundant union.
Complexity & use
Amortized O(α(V)) per operation with union by size and path compression, O(V) storage; a single operation is not promised constant worst-case time.
Try it
Start with five vertices and join (0,1), (1,2), (3,4), then join (0,2) again.
Worked solution
Five components become four, three and two. The final union finds both endpoints already rooted in the same component, so the count remains two. Vertices 0 and 2 are connected; 0 and 4 are not.
Change the constraint
Why does finding a root not provide the route between the original graph vertices?
How did you do?
Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.
Not marked. Progress stays on this browser, separate from course completion.
Primary references
Checked 2026-10-27. Use documentation for your pinned runtime, driver and tool version.