n nodes, n edges — a tree plus exactly one extra. Walk the edges in order and ask one question of each: are these two ends already in the same component? The first edge for which the answer is yes is the redundant one. The structure that answers it is a forest of parent pointers, drawn here beside the graph, so that find climbing to a root and union re-rooting are things you watch rather than infer.
u
endpoint v
where find is standing
set root / united edge
edge not yet considered
"A valid tree with $n$ vertices has exactly $n-1$ edges and 0 cycles. Since the input gives $n$ edges, exactly one edge must be creating a cycle."
"Initialize each vertex in its own component (parent[i] = i). For each edge (u, v), find their root representatives. If find(u) == find(v), they already belong to the same component—this edge creates the cycle!"
"DFS would require running a search for each edge ($O(n^2)$ total). Union-Find checks connectivity and merges in near-$O(1)$ amortized time ($O(n \cdot \alpha(n))$ overall)."
"Path compression flattens the tree during find: parent[x] = find(parent[x]). Union by rank/size hangs smaller trees under larger roots, preventing degenerating into chains."
find walks a chain instead of a stub: the same answer, arrived at in O(n²). Flip the toggle and read the two numbers in the second card.