We have a weighted undirected graph and we need to classify every edge into one of three categories: critical (must be in every MST), pseudo-critical (appears in some but not all MSTs), or neither (never appears in any MST).
A critical edge is one whose removal would either disconnect the graph or force a higher MST weight. If removing an edge makes it impossible to connect all vertices, or if the cheapest spanning tree without that edge costs more than the original MST, then that edge is critical.
A pseudo-critical edge is harder to detect. It is not critical (so at least one MST exists without it), but it does appear in at least one valid MST. To test this, force-include the edge and then build the rest of the MST around it. If the total weight still equals the original MST weight, that edge can participate in some MST.
Both tests rely on the same building block: Kruskal's algorithm with a Union-Find data structure to compute MST weights. We compute a baseline MST weight once, then test each edge by either excluding it or force-including it and comparing the result against the baseline.
2 <= n <= 100 -> Very small vertex count. Even O(n^2) per edge or O(E * E) overall is fine.1 <= edges.length <= min(200, n * (n - 1) / 2) -> At most 200 edges. We can afford to run a full MST computation for each edge (200 MST computations, each O(E * alpha(n))).1 <= weight_i <= 1000 -> With at most 200 edges, the total MST weight is at most 199 * 1000 < 200,000, which fits in a 32-bit int. No overflow handling is needed.The definitions translate directly into a procedure: generate every possible spanning tree, keep the ones with minimum weight, then check which edges appear in all of those MSTs (critical) versus only some of them (pseudo-critical).
For a graph with E edges and n vertices, a spanning tree uses exactly n-1 edges. We enumerate all C(E, n-1) combinations of edges, check whether each forms a spanning tree, and if so, track its total weight. After finding the minimum weight, we classify edges by which MSTs they appear in.
This is correct but combinatorially explosive. With E = 200 and n = 100, C(200, 99) is astronomically large. Even for moderate inputs the number of combinations grows past anything we can iterate over.
Loading animation...
This approach finds the answer but enumerates an exponential number of edge subsets. The next approach avoids enumeration entirely by classifying each edge with at most two MST computations.
Instead of finding all MSTs and then checking membership, we classify each edge with two tests:
First compute the baseline MST weight. Then for each edge, run the exclusion test. If the weight goes up, the edge is critical. If not, run the inclusion test, and if that weight matches the baseline, the edge is pseudo-critical. An edge that fails both tests never appears in any MST and is left out of both lists.
The exclusion test detects critical edges. A critical edge is one that appears in every MST, so removing it from the graph must raise the minimum achievable spanning-tree weight above the baseline. If the graph becomes disconnected without the edge, the edge was a bridge, and a bridge is in every spanning tree, so it is critical too. Both outcomes are captured by "weight without the edge > baseline" because a disconnected build returns infinity.
The inclusion test detects pseudo-critical edges constructively. Forcing the edge in and completing the tree with Kruskal's produces the cheapest spanning tree that contains that edge. If that cost equals the baseline, the result is itself a valid MST containing the edge, which proves the edge belongs to at least one MST. Running the inclusion test only after the exclusion test fails guarantees the edge is not also critical, so it is correctly placed in the pseudo-critical group.
i:i. If the resulting weight > baseline or the graph is disconnected, edge i is critical.i first, then run Kruskal's on the remaining edges. If the total weight equals the baseline, edge i is pseudo-critical.Loading animation...