Minimum Spanning Tree Operations
Node
Edge→
RunStart
100%
Ctrl + scroll to zoom
Build a minimum spanning tree - see edges chosen to connect all vertices with least cost.
Time O(E log V) · Space O(V)
import heapq
from typing import Dict, Set, List, Any, Tuple
def mst(graph: Dict[Any, Dict[Any, float]]) -> List[Tuple[Any, Any, float]]:
"""
Find the Minimum Spanning Tree using Prim's algorithm.
Args:
graph: Weighted adjacency list {node: {neighbor: weight, ...}}
Returns:
List of edges in MST as (from, to, weight) tuples
Raises:
ValueError: If graph is empty or disconnected
"""
if not graph:
raise ValueError("Graph is empty")
mst_edges = []
visited: Set[Any] = set()
# Start from arbitrary vertex
start = next(iter(graph))
visited.add(start)
# Min-heap: (weight, from_node, to_node)
edges_heap = []
for neighbor, weight in graph[start].items():
heapq.heappush(edges_heap, (weight, start, neighbor))
while edges_heap and len(visited) < len(graph):
weight, frm, to = heapq.heappop(edges_heap)
if to in visited:
continue # Skip - would create cycle
# Add edge to MST
mst_edges.append((frm, to, weight))
visited.add(to)
# Add new edges from the newly added vertex
for neighbor, edge_weight in graph[to].items():
if neighbor not in visited:
heapq.heappush(edges_heap, (edge_weight, to, neighbor))
if len(visited) != len(graph):
raise ValueError("Graph is disconnected - MST does not exist")
return mst_edges
def mst_weight(graph: Dict[Any, Dict[Any, float]]) -> float:
"""
Calculate the total weight of the Minimum Spanning Tree.
Args:
graph: Weighted adjacency list
Returns:
Total weight of the MST
"""
edges = mst(graph)
return sum(weight for _, _, weight in edges)
def mst_as_graph(graph: Dict[Any, Dict[Any, float]]) -> Dict[Any, Dict[Any, float]]:
"""
Return the MST as an adjacency list (undirected).
Args:
graph: Weighted adjacency list
Returns:
MST as weighted adjacency list
"""
edges = mst(graph)
result: Dict[Any, Dict[Any, float]] = {node: {} for node in graph}
for frm, to, weight in edges:
result[frm][to] = weight
result[to][frm] = weight
return result
# Example usage and demonstration
if __name__ == "__main__":
# Example weighted undirected graph
#
# A ---4--- B
# | \ |
# 2 3 1
# | \ |
# C ---5--- D
#
example_graph = {
"A": {"B": 4, "C": 2, "D": 3},
"B": {"A": 4, "D": 1},
"C": {"A": 2, "D": 5},
"D": {"A": 3, "B": 1, "C": 5},
}
print("MST Edges (Prim):", mst(example_graph))
print("MST Total Weight:", mst_weight(example_graph))
print("MST as Graph:", mst_as_graph(example_graph))
# Disconnected graph (should raise error)
disconnected = {
"A": {"B": 1},
"B": {"A": 1},
"C": {"D": 2},
"D": {"C": 2},
}
try:
mst(disconnected)
except ValueError as e:
print(f"Disconnected graph error: {e}")
A minimum spanning tree (MST) connects all vertices of a weighted undirected graph with the minimum total edge weight and no cycles. Prim's algorithm grows the tree from a starting vertex, while Kruskal's sorts edges globally and adds them if they don't form a cycle.
Prim's: start from any vertex, repeatedly add the cheapest edge connecting the tree to an unvisited vertex. Kruskal's: sort all edges by weight, then add each edge if it connects two different components (checked via Union-Find).