Have you ever wondered how to group connected components in a graph and check whether two nodes belong to the same group? That’s exactly where Union-Find(also called Disjoint Set Union or DSU) comes into play.
Let’s understand this through a real example — solving the Number of Good Pathsproblem using Union-Find.
✨ What is Union-Find?
Union-Find is a smart way to:
- Group items together (called sets)
- Find whether two items belong to the same group (or set)
- Merge two groups together (union)
It’s widely used in problems where you need to track connected components — especially in graphs.
💡 When to Use Union-Find?
Look for patterns like:
- “Are these two nodes connected?”
- “How many groups/components exist?”
- “Merge if two nodes have some condition met”
- “Check cycles in undirected graphs”
- “Build groups with some rules/conditions”
If the problem talks about connected nodes, merging subsets, or tracking isolated components, Union-Find is likely the tool you need!
🚩 Problem Intuition: Number of Good Paths
📌 Problem:
Given a tree (undirected graph) and a value for each node, you must count all “good paths”.
A good path is a path where:
- The start and end values are equal
- All the values on the path are less than or equal to this value
🧠 Intuition:
- Every single node is a valid “good path” (path of length 0).
- Suppose a node has the maximum value
v
, and there are k such nodes, then we can formk*(k-1)/2
pairs among them. Each pair is a valid good path. - But these nodes must be connected. That’s where Union-Find helps us to build and track connected components.
🔁 How Does the Algorithm Work?
We solve this bottom-up, not by cutting the tree but by joining smaller value nodes first.
Step-by-step:
- Initialize each node as its own set using Union-Find.
- Sort all edges by the maximum value of the two connecting nodes.
- For each edge
(i, j)
with valuev
:- If
vals[i] <= v
andvals[j] <= v
, try to merge their sets. - If both ends have the same value
v
, we can form new good paths =count[i] * count[j]
.
- If
- Update the parent and value count using Union-Find.
- Keep adding new good paths to the result.
🧮 Python Code (with Explanation)
from collections import Counter
def numberOfGoodPaths(vals, edges):
n = len(vals)
res = n # Every single node is a good path
parent = list(range(n)) # DSU parent
count = [Counter({vals[i]: 1}) for i in range(n)] # Count of value v in each set
# Sort edges based on max value of the two connecting nodes
edges = sorted([max(vals[i], vals[j]), i, j] for i, j in edges)
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # Path compression
return parent[x]
for v, i, j in edges:
pi, pj = find(i), find(j)
if pi == pj:
continue
# Get count of value `v` in both sets
ci, cj = count[pi][v], count[pj][v]
# Number of good paths is combinations of ci and cj
res += ci * cj
# Merge sets
parent[pj] = pi
count[pi] += count[pj]
return res
⏱️ Time and Space Complexity
- Time:
O(n * α(n))
whereα(n)
is the inverse Ackermann function (very small) - Space:
O(n)
for parent tracking and value counting
🧠 Key Takeaways
- Union-Find is a perfect choice when you need to group and check connectivity efficiently.
- Look for “can be connected” + “same condition” patterns — Union-Find will likely help!
- This problem smartly builds sets from smaller values upward and uses merging to track connected values.