Arian Soleimanzadeh
  • Home
  • Blog
  • Podcasts
  • Videos
  • Contact
العربيةArabic
DeutschGerman
EnglishEnglish
فارسیPersian
한국어Korean
中文Chinese
Panel•Quick Contact

Languages

Choose your interface locale

ar

العربية

Arabic

de

Deutsch

German

en

English

English

fa

فارسی

Persian

ko

한국어

Korean

zh

中文

Chinese

Get Appointment

Drop a quick message — I’ll reply as soon as possible.

LinkedInFast response
Home/Articles/Prim's Algorithm: Minimum Spanning Trees, Heaps and Cut Property
AlgorithmsGraph AlgorithmsArticle

Prim's Algorithm: Minimum Spanning Trees, Heaps and Cut Property

A complete Prim guide covering MST fundamentals, the cut property, min-heaps, disconnected graphs, dense vs sparse graphs, and comparisons with Kruskal and Dijkstra.

August 21, 202614 min read0 Views
#Graph#Algorithms#Prim's Algorithm#Minimum Spanning Tree#MST#Greedy#Min-Heap#JavaScript#TypeScript

Arian Soleimanzadeh

Software Engineer & Researcher

Prim's Algorithm and Minimum Spanning Tree visual guide

Arian Soleimanzadeh

AI · Code · Product

Research + Engineering

Prim's Algorithm is a greedy algorithm for constructing a Minimum Spanning Tree (MST) of a weighted, undirected, connected graph.

Its objective is not shortest paths from a source. Instead, it minimizes the total weight of the edges used to connect all vertices.

Minimum Spanning Tree

A spanning tree:

  • includes every vertex,
  • is connected,
  • contains no cycle,
  • has exactly V-1 edges.

An MST is the spanning tree with minimum total edge weight.

Core idea

Prim grows one tree.

At every step:

  1. keep a set of vertices already inside the tree,
  2. consider edges crossing from visited to unvisited vertices,
  3. choose the minimum-weight crossing edge,
  4. add the new vertex,
  5. repeat until all vertices are included.

Why the greedy choice works

Prim relies on the Cut Property:

For any cut of the graph, a lightest edge crossing that cut belongs to some MST.

At each step, the visited/unvisited partition forms exactly such a cut.

JavaScript with a priority queue concept

JavaScript
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
function prim(graph, start) {
  const visited = new Set();
  const mst = [];
  const candidates = [
    [0, null, start]
  ];

  let totalWeight = 0;

  while (candidates.length > 0) {
    candidates.sort(
      (a, b) => a[0] - b[0]
    );

    const [
      weight,
      from,
      node
    ] = candidates.shift();

    if (visited.has(node)) {
      continue;
    }

    visited.add(node);

    if (from !== null) {
      mst.push([
        from,
        node,
        weight
      ]);

      totalWeight += weight;
    }

    for (
      const [next, cost]
      of graph[node] ?? []
    ) {
      if (!visited.has(next)) {
        candidates.push([
          cost,
          node,
          next
        ]);
      }
    }
  }

  return {
    mst,
    totalWeight
  };
}

For production use, replace repeated sorting with a real min-heap.

Prim vs Kruskal

Both build MSTs.

Prim:

Code
1
grows one connected tree

Kruskal:

Code
12
sorts edges globally
+ uses Union-Find

Prim is often natural with adjacency lists or matrices.

Kruskal is especially convenient when the graph is already represented as an edge list.

Prim vs Dijkstra

This distinction is crucial.

Prim minimizes:

Code
1
total weight of the spanning tree

Dijkstra minimizes:

Code
1
distance from one source to every vertex

They can both use a priority queue, but their greedy keys and objectives are different.

Negative edge weights

Negative edges are allowed in MST problems.

Unlike shortest-path problems, a negative cycle does not create an unbounded optimum because an MST never contains a cycle.

Disconnected graphs

A single MST for the entire graph exists only if the graph is connected.

For disconnected graphs, run Prim independently on each component to obtain a Minimum Spanning Forest.

Dense vs sparse graphs

With an adjacency matrix and linear minimum-key selection:

Code
1
O(V²)

can be attractive for dense graphs.

With adjacency lists and a binary heap:

Code
1
O(E log V)

is standard.

Edge-based vs key-based Prim

Two common implementations exist.

Edge-based Prim stores candidate edges:

Code
1
(weight, from, to)

Key-based Prim stores, for each unvisited vertex, the cheapest known connection into the current tree.

Both implement the same greedy principle.

Multiple MSTs

If all edge weights are distinct, the MST is unique.

With equal weights, several different MSTs may have the same minimum total cost.

Tie-breaking can therefore affect the exact edge set.

Real-world applications

Prim can model cost-minimal connection backbones such as:

  • fiber layouts,
  • cable networks,
  • basic data-center interconnects,
  • utility connections,
  • sensor networks,
  • road or pipeline design abstractions.

However, a pure MST minimizes cost, not redundancy.

Reliability caveat

An MST is a tree, so it contains no alternate route.

Every selected edge is a bridge in that tree.

Real production networks often add extra links after an MST-style cost baseline to improve fault tolerance.

MST and clustering

MSTs also appear in clustering.

A common idea is to build an MST and remove one or more of its largest edges to split the data into groups.

Directed graphs

Classic Prim applies to weighted undirected graphs.

Directed minimum-spanning structures require different algorithms such as Chu-Liu/Edmonds for arborescences.

Edge cases

  • empty graph,
  • one vertex,
  • disconnected graph,
  • duplicate edges,
  • self-loops,
  • negative weights,
  • equal weights,
  • invalid start vertex.

TypeScript

TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
type NodeId = string;

type Neighbor = [
  node: NodeId,
  weight: number
];

type Graph =
  Record<NodeId, Neighbor[]>;

type MSTEdge = [
  from: NodeId,
  to: NodeId,
  weight: number
];

type PrimResult = {
  edges: MSTEdge[];
  totalWeight: number;
  connected: boolean;
};

function prim(
  graph: Graph,
  start: NodeId
): PrimResult {
  const nodes = new Set<NodeId>();

  for (
    const [u, neighbors]
    of Object.entries(graph)
  ) {
    nodes.add(u);

    for (const [v] of neighbors) {
      nodes.add(v);
    }
  }

  if (!nodes.has(start)) {
    return {
      edges: [],
      totalWeight: 0,
      connected: false
    };
  }

  const visited = new Set<NodeId>();
  const candidates:
    Array<[number, NodeId | null, NodeId]> = [
      [0, null, start]
    ];

  const edges: MSTEdge[] = [];
  let totalWeight = 0;

  while (candidates.length > 0) {
    candidates.sort(
      (a, b) => a[0] - b[0]
    );

    const [
      weight,
      from,
      node
    ] = candidates.shift()!;

    if (visited.has(node)) {
      continue;
    }

    visited.add(node);

    if (from !== null) {
      edges.push([
        from,
        node,
        weight
      ]);

      totalWeight += weight;
    }

    for (
      const [next, cost]
      of graph[node] ?? []
    ) {
      if (!visited.has(next)) {
        candidates.push([
          cost,
          node,
          next
        ]);
      }
    }
  }

  return {
    edges,
    totalWeight,
    connected:
      visited.size === nodes.size
  };
}

Complexity

With adjacency list + binary heap:

Code
1
O(E log V)

A simple edge-heap implementation may also be described as:

Code
1
O(E log E)

With an adjacency matrix:

Code
1
O(V²)

Common mistakes

  • confusing Prim with Dijkstra,
  • applying classic Prim to directed graphs,
  • forgetting disconnected graphs,
  • using repeated array sorting instead of a heap at scale,
  • forgetting to represent undirected edges in both adjacency directions,
  • assuming MST means high reliability.

Summary

Prim's algorithm solves:

Code
123
connect every vertex
with minimum total edge cost
without cycles

It is one of the two standard MST algorithms, alongside Kruskal.

Use it when the problem is a weighted undirected connectivity problem rather than a shortest-path problem.

Article details

Publication metadata, reading time and live view information.

Published

August 21, 2026

Updated

August 23, 2026

Reading time

14 min read

Views

0

Author

Arian Soleimanzadeh

Previous article

Floyd-Warshall: All-Pairs Shortest Paths with Dynamic Programming

Next article

Eulerian Path & Circuit: Using Every Edge Exactly Once

Arian Soleimanzadeh

Personal portfolio focused on modern web engineering, UI systems, and practical AI products — clean code, clean design.

Quick Links

  • About
  • Blog
  • Contact

Contact

  • soleimanzadeh.a.work@gmail.com
  • soleimanzadeh.uni@gmail.com

Availability: Weekdays

Typically replies within 24h.

Newsletter

Get updates on posts, projects, and new releases.

© 2026 ariansoleimanzadeh.site — All rights reserved.

LinkedIn