Sometimes you need groups, not routes
Picture
Roads are added over time. Repeatedly, you ask whether two towns are connected. You do not need the route itself. A disjoint-set structure stores which group each town belongs to and merges groups when a new road joins them.
Predict
If a new undirected edge connects two vertices already in the same component, does it merge two components? What does it tell you about cycles?
Reveal the reasoning
It does not merge components. There was already a path between the endpoints, so adding that edge closes a cycle. This is the useful test behind Kruskal’s spanning-tree algorithm.
Go deeper: representatives summarize membership
class DisjointSet:
def __init__(self, n):
self.parent = list(range(n))
self.size = [1] * n
def find(self, x):
while x != self.parent[x]:
self.parent[x] = self.parent[self.parent[x]]
x = self.parent[x]
return x
def union(self, a, b):
a, b = self.find(a), self.find(b)
if a == b:
return False
if self.size[a] < self.size[b]:
a, b = b, a
self.parent[b] = a
self.size[a] += self.size[b]
return True
groups = DisjointSet(4)
assert groups.union(0, 1)
assert groups.union(1, 2)
assert groups.find(0) == groups.find(2)
assert not groups.union(0, 2)
assert groups.find(3) != groups.find(0)
The parent array represents a forest of group representatives, not the original graph’s road paths. Union by size attaches a smaller representative tree under a larger one. Path halving shortens future representative lookups while preserving membership.
Initialization and space are O(V). With these optimizations, a sequence of operations has amortized O(α(V)) time per operation, where the inverse Ackermann function grows extremely slowly. That is an amortized statement, not a promise that each individual operation does exactly constant work.
For a fixed graph and a few connectivity questions, BFS or DFS may be simpler. Disjoint sets fit repeated merges and membership queries. They do not directly report shortest paths, directed reachability, or handle arbitrary deletions.
Analogy limit: sharing a representative means connected by some path; it does not mean directly adjacent.
Change one rule
Roads can be deleted as well as added. Can this implementation simply “undo a union” locally?
Check the variation
No. Removing an edge may or may not split a component, and the representative forest has discarded the information needed to decide. Consider recomputation or a specialized offline/dynamic connectivity method.
Connect
Minimum spanning trees combine this connectivity test with a greedy edge rule. Recognition distinguishes “same component” from “cheapest route.”