Problem Statement
Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree
You are given a connected graph. Think of vertices as cities (numbered 0 to n-1) and edges as roads between cities. Each road has a weight, which is its cost. We want to connect every city using the cheapest set of roads possible, with no wasted loops. That cheapest set is called a minimum spanning tree, or MST. "Spanning" means it touches every city, and "minimum" means the total road cost is as small as it can be. Your job is to sort the roads into two groups. A critical road is one you cannot do without: if you delete it, the cheapest way to connect all cities becomes more expensive (or becomes impossible). A pseudo-critical road is one that is not strictly required, but could be part of some cheapest plan if you chose to use it.
Signals to notice
Brute force first
For each edge, compute MST without it and with it forced in. Two MST computations per edge. That instinct is useful because it follows the prompt literally, but it usually keeps revisiting work the problem is begging you to organize.
The key insight
Compute the base MST weight. For each edge: (1) exclude it and compute MST — if weight increases or MST is disconnected, it's critical. (2) Force-include it and compute MST — if weight equals base, it's pseudo-critical. but with Kruskal's, each MST is fast. The goal is not to be clever for its own sake, but to remember the one relationship that keeps the solution grounded as you move forward.
Trace it on n=5, edges=[[0,1,1],[1,2,1],[2,3,2],[0,3,2],[0,4,3],[3,4,3],[1,4,6]]
sort by weight, keep orig index: order = 0(w1),1(w1),2(w2),3(w2),4(w3),5(w3),6(w6)
base MST (Kruskal): add 0{0,1}, add 1{0,1,2}, add 2{0,1,2,3}, skip 3 (cycle), add 4{all}; w=1+1+2+3=7, cnt=4=n-1 -> base=7
edge 0: skip=0 -> MST uses {1,2,3,4} w=1+2+2+3=8 > 7 -> critical; crit=[0]
edge 1: skip=1 -> MST uses {0,2,3,4} w=1+2+2+3=8 > 7 -> critical; crit=[0,1]
edge 2: skip=2 -> 7 (not >base); include=2 -> 7 == base -> pseudo; pseudo=[2]
edge 3: skip=3 -> 7 (not >base); include=3 -> 7 == base -> pseudo; pseudo=[2,3]
edges 4,5 (w3): each skip -> 7 (not >base); include -> 7 == base -> pseudo; pseudo=[2,3,4,5]
edge 6 (w6): skip -> 7 (not >base); include=6 -> 10 != 7 -> neither
return [crit, pseudo] = [[0,1],[2,3,4,5]]What must stay true
A critical edge must be in every MST. A pseudo-critical edge appears in at least one MST but not all. Testing exclusion catches critical edges; testing forced inclusion catches pseudo-critical ones. If that remains true after every update, the rest of the reasoning has a stable place to stand.
Shape of the loop
sort edges by weight, keep original index
base = mstWeight() # Kruskal once
crit, pseudo = [], []
for each edge i (in sorted order):
if mstWeight(skip=i) > base: crit.add(i) # removal raises weight -> critical
elif mstWeight(include=i) == base: pseudo.add(i) # forcing it keeps base -> pseudo
return [crit, pseudo]Pseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Not testing both exclusion AND forced inclusion — an edge could be neither critical nor pseudo-critical. Also, a disconnected graph after exclusion means the edge was a bridge, making it critical. Most mistakes here are not about syntax; they come from losing track of what your state, pointer, or structure is supposed to mean.