A cheapest network is not a set of cheapest routes
Picture
Connect every town while minimizing the total cost of installed roads. This is a minimum spanning tree problem on a connected, undirected weighted graph. Kruskal’s algorithm considers cheap edges first and takes an edge only when it joins two different components.
Predict
Edges are A–B:2, B–C:2, and A–C:3. Does the cheapest spanning tree also contain the cheapest route from A to C?
Reveal the reasoning
No. The spanning tree uses the two cost-2 edges, total installation cost 4. Its A-to-C route costs 4, while the original graph has a direct cost-3 route. Network cost and single-source route cost are different objectives.
Go deeper: connectivity supplies the test; exchange supplies the proof
When considering the cheapest edge that crosses between current components, take the cut separating one component from the others. Some optimal spanning tree must connect across that cut. If it lacks this cheap edge, add it, creating a cycle, and remove a crossing edge no cheaper than it. Connectivity is preserved and total cost does not increase. Repeating this argument justifies the commitments.
def spanning_tree(n, edges):
parent, size = list(range(n)), [1] * n
def find(x):
while x != parent[x]:
parent[x] = parent[parent[x]]
x = parent[x]
return x
chosen, total = [], 0
for u, v, weight in sorted(edges, key=lambda edge: edge[2]):
a, b = find(u), find(v)
if a == b:
continue
if size[a] < size[b]:
a, b = b, a
parent[b] = a
size[a] += size[b]
chosen.append((u, v, weight))
total += weight
if n > 0 and len(chosen) != n - 1:
return None
return total, chosen
assert spanning_tree(3, [(0, 1, 2), (1, 2, 2), (0, 2, 3)])[0] == 4
assert spanning_tree(3, [(0, 1, 2)]) is None
assert spanning_tree(1, []) == (0, [])
Assume valid integer labels 0..n-1; the empty graph returns an empty result by convention. Edge sorting dominates, giving O(E log E + V) time with near-constant amortized disjoint-set operations, and O(V+E) extra space in this implementation. Equal weights can yield several optimal trees. Negative weights do not break the cut exchange argument.
Prim’s algorithm is a related approach that grows one connected tree by repeatedly choosing a cheapest edge crossing its boundary. Its priority is edge connection cost; Dijkstra prioritizes accumulated route cost.
Analogy limit: directed networks require a different formulation. Do not remove edge directions and assume the resulting spanning tree solves a directed connectivity requirement.
Change one rule
The graph is disconnected. What useful result can Kruskal still produce if the task permits it?
Check the variation
A minimum spanning forest, one minimum spanning tree per connected component. The sample deliberately returns None when a single spanning tree is impossible; a forest API would instead return the selected edges and component information.
Connect
Components establish what can be connected. Recognition distinguishes a network-design objective from a route-finding objective.