Skip to main content
Artificial Computational Intelligence

Minimum Spanning Trees and Dynamic Programming

Published: 2026-08-09
Level: postgraduate
Audience: Postgraduate students in Artificial Computational Intelligence

Prerequisite Knowledge

This lecture builds on the following concepts from earlier lectures. If any feel unfamiliar, review the linked notes before proceeding.

Previously Covered in This Subject

  • Graph basics — vertices, edges, paths, and weighted graphs — covered in Lecture 10
  • Dijkstra's algorithm — single-source shortest paths and the greedy strategy behind it — covered in Lecture 10
  • Divide and conquer — the strategy this lecture contrasts with dynamic programming — covered in Lecture 9

This session covers two pieces. First, the minimum spanning tree problem and the two greedy algorithms that solve it — Prim's algorithm and Kruskal's algorithm. Both solve the same problem, but each applies the greedy idea in its own way. Second, the third and last design strategy of the course: dynamic programming. The technique is built up with two main examples — Fibonacci numbers and the 0/1 knapsack problem — and closes with the idea of pseudo-polynomial time, which sets up the next session's discussion of NP problems.

11.1 Graphs — Recap

11.1.1 Where We Left Off — Dijkstra's Algorithm

Where did the course stop last time? Under graphs, we were discussing Dijkstra's algorithm. Let's place it before moving on, because today's two minimum spanning tree algorithms are its direct descendants.

Dijkstra's algorithm solves the single source shortest path problem: its objective is to find the shortest path from a single source vertex to all the other vertices of a weighted graph. It falls under the greedy method, the design strategy that was being discussed — a strategy that works on optimization problems by making the best local choice at every step.

Both the greedy method and Dijkstra's algorithm are the direct background for today's minimum spanning tree algorithms. Prim's algorithm and Kruskal's algorithm both apply the greedy idea, but in two different ways — Prim's grows one tree exactly like Dijkstra's grows a shortest-path tree, while Kruskal's works globally on edges. Knowing Dijkstra's algorithm well makes today's material much easier: the pseudocode, the heap-based analysis, and even the "initialize single source" step all carry over.

Hook for this session: you already know how to find the cheapest way to reach every other city from one city (Dijkstra). Today's question is different: what is the cheapest way to connect all the cities into one network — and then the follow-up, how do you do it with the same greedy mindset?

11.1.2 What a Graph Is

A graph is a way of modeling connections between things. Formally, a graph is an ordered pair

where is a set of vertices (also called nodes) and is a collection of pairs of vertices called edges. The rough everyday definition — "a collection of vertices and edges" — is fine for casual talk, but the conceptual meaning of the ordered-pair definition is what matters. Definitions do not need to be memorized word for word, but the conceptual understanding is very important.

The word "ordered pair" carries a real idea: a graph is not just a pile of parts, it is a structured object whose two components play different roles. is a set — its elements are distinct and unordered. is a collection of pairs — each edge is defined by the two vertices it joins, and the edge connects those two vertices. For an edge , the vertices and are called its endpoints; two vertices joined by an edge are adjacent; and an edge whose two endpoints are the same vertex is a loop. The number of edges leaving a vertex is its degree. Today's graphs are undirected (an edge is a two-way connection) and weighted (each edge carries a number called its weight).

Intuition: think of a city map. The traffic signals are the vertices, and the roads are the edges. The ordered-pair definition just says: first list the signals, then list which pairs of signals are joined by a road. The same idea models a computer network (routers and cables), a social network (people and friendships), or a circuit (pins and wires).

Scope: the ordered-pair definition works for any graph, but the minimum spanning tree story that follows assumes the graph is connected (there is a path between every pair of vertices), undirected (edges go both ways), and weighted (every edge has a cost). If the graph is disconnected, no spanning tree exists at all — there is no way to link all vertices without leaving some part unreachable.

Definition (graph): a graph is an ordered pair , where is the set of vertices and is the collection of edges, each edge being a pair of vertices.

Q: What is a graph? A: It is an ordered pair : is a set of vertices or nodes, and is a collection of pairs of vertices called edges. The rough everyday definition, a collection of vertices and edges, is acceptable, but you should understand the ordered-pair idea properly — the conceptual understanding matters more than memorizing the wording.

Recap + bridge: a graph is an ordered pair of vertices and edges, and Dijkstra's algorithm is the greedy shortest-path algorithm from the previous session. Both facts feed directly into the next concept: a spanning tree is a special subgraph built on the same and .

11.2 Spanning Subgraphs and Spanning Trees

11.2.1 Spanning Subgraph

A spanning subgraph of a graph is a subgraph of that contains all the vertices of . What it will not contain, in general, are all the edges of the original graph — a spanning subgraph is a subgraph, not the graph itself.

The name says it: the word "spanning" means it spans (covers) all the vertices, but only some of the edges. Every vertex of appears, while edges may be dropped. The concept matters because a graph can have many different spanning subgraphs: keep all the vertices, keep different choices of edges, and you get different spanning subgraphs of the same graph.

Intuition: a full map of a city's road network has every junction and every road. A spanning subgraph is a redrawn map that keeps every junction but deletes some roads — you can still see the whole city, just with fewer connections shown.

Definition (spanning subgraph): a spanning subgraph of a graph is a subgraph that contains all the vertices of . It may contain fewer edges than , but never a different set of vertices.

Q: Is a graph and a spanning subgraph different? A: Yes. A spanning subgraph contains all the vertices of the given graph, but it may not contain all the edges of the original graph. A spanning subgraph is a subgraph, not the graph itself.

11.2.2 Spanning Tree

A spanning tree of a graph is a spanning subgraph that is itself a tree. Here "tree" is used in its precise graph sense: the structure is connected — you can walk from any vertex to any other vertex along edges — and it has no cycles (no loops). Equivalently, there is exactly one path between any two vertices.

Putting the two ideas together, a spanning tree of :

  • has all the vertices of (it spans),
  • does not have all the edges of (only some of them),
  • is connected,
  • contains no cycles.

A useful counting consequence: any tree on vertices has exactly edges. So a spanning tree of a graph with vertices always picks exactly of the graph's edges — enough to connect everything, never more, because an extra edge would close a cycle.

One note on the wording of the original discussion: it was said that the spanning tree "will not be connected." That phrasing is misleading — a tree is by definition connected and acyclic. What the discussion meant is that the tree will not contain every connection of the original graph: some edges are left out, yet the chosen edges still keep the whole structure connected. Connectedness is exactly what makes it a tree rather than a forest.

Intuition: a spanning tree is like the minimum wiring of a campus intercom system: every room gets a connection, there is a path between any two rooms, and no wire loop is wasted — remove any single wire and some pair of rooms loses its only connection.

Pitfalls:

  • Thinking a spanning tree must contain all the edges of the graph. It does not — it contains exactly edges for vertices.
  • Thinking "no cycles" alone is enough. A graph with no cycles but several separate pieces is a forest, not a tree; a spanning tree must also be connected.
  • Confusing a spanning tree with the graph itself: the graph has every edge, the spanning tree keeps only a chosen subset.

Recap + bridge: a spanning subgraph keeps all vertices and drops some edges; a spanning tree is a spanning subgraph that is connected and cycle-free, with exactly one path between any two vertices. Next, weights come in: among all spanning trees of a weighted graph, which one is cheapest?

11.3 Minimum Spanning Trees

11.3.1 Definition and Intuition

The minimum spanning tree (MST) is defined for weighted graphs: every edge carries a number called its weight — a cost, a distance, a price. The total weight of a spanning tree is the sum of its edge weights:

where is the spanning tree, ranges over the edges of , and is the weight of edge . A minimum spanning tree is a spanning tree of a weighted graph with the minimum total edge weight — the minimum-cost spanning tree. The idea in one line: after constructing a spanning tree, if that spanning tree carries the minimum total edge weight, we call it a minimum spanning tree.

Hook: suppose a phone company will connect cities but charges a different price for every pair of cities. You want every office connected with the smallest possible total bill. That is the minimum spanning tree problem — and it shows up every time someone wires, routes, or links a set of locations.

Intuition: imagine connecting several places at minimum total cost. In a transportation network, from a common hub (say Bangalore) we want the minimum-distance routes to several destinations (Hyderabad, Chennai, other places). In a communication network, we want the cheapest way of laying cables to connect every building within a campus, or to connect different telephone exchanges. The lecture illustrated this with a complete graph: the solid lines connect all the vertices — that is a spanning tree — and the dotted lines are the remaining edges. You calculate the edge weights, you sum them, and if that sum is the minimum possible total edge weight, you have a minimum spanning tree. If you can construct any other spanning tree with a smaller weight, that smaller one becomes the minimum spanning tree.

Definition (minimum spanning tree): given a connected, undirected, weighted graph with weight function , a minimum spanning tree is a spanning tree of that minimizes . The tree itself is a set of edges (for vertices) that keeps every vertex connected.

Scope: the MST problem assumes the graph is connected and undirected, and that every edge has a weight. If the graph is disconnected, no spanning tree exists — the problem simply has no solution. If weights are negative the definitions still make sense, and the two greedy algorithms studied next still work, because they only ever compare and sum edge weights.

11.3.2 Uniqueness of the MST

A graph can have more than one minimum spanning tree. The exception: if all the edge weights are unique — pairwise distinct — then there is only a single minimum spanning tree.

The phrase "pairwise distinct" is the whole catch: every pair of edges in the whole graph must carry different weights. If two edges somewhere in the graph share a weight, the MST can cease to be unique. Two different trees may then achieve the same minimum total weight, and each one is a perfectly valid minimum spanning tree.

Uniqueness rule: the MST of a graph is unique if and only if all edge weights are pairwise distinct. If any two edges share a weight, the graph may have several MSTs with the same total weight.

11.3.3 Worked Example — Three Spanning Trees of One Graph

Consider a small graph on vertices A, B, C, D, E, with edge weights marked on the edges. The lecture drew three different spanning trees for this same graph and gave their totals. Only the totals were stated in the discussion; the weight assignment below is a consistent one that reproduces exactly those totals, so every step can be checked.

The graph has six edges with these weights:

Edge A–B A–C B–C C–D D–B D–E
Weight 21 18 13 15 19 22

Worked example — three spanning trees, one winner.

  • Tree 1: edges A–C, C–D, D–B, D–E. All vertices are connected: A reaches D through C, and D reaches B and E directly. Four edges join five vertices with no cycle, so this is a spanning tree. Total weight: 74.
  • Tree 2: edges A–B, B–C, C–D, D–E. The chain A–B–C–D–E connects everything with no cycle. Total weight: 71.
  • Tree 3: edges A–C, C–B, B–D, D–E. The chain A–C–B–D–E connects everything with no cycle. Total weight: 72.

The tree with total weight 71 (Tree 2) is the minimum spanning tree of this graph: no spanning tree of the graph has a smaller total weight. Since every edge weight in this graph is distinct, the graph has exactly one MST.

Sense-check: each tree uses exactly edges for 5 vertices, and 71 < 72 < 74, so Tree 2 beats both alternatives — and no other spanning tree exists with a smaller total, because all weights are pairwise distinct.

11.3.4 Worked Example — Two MSTs of Equal Weight

When weights repeat, the MST may be non-unique. The lecture drew two minimum spanning trees, call them MST1 and MST2, for the same weighted graph.

Worked example — the single-edge swap.

The only difference between MST1 and MST2 is one edge: in the first tree one edge is inserted, and in the second tree a different edge is used instead — but the two edges carry the same weight (call it ). Because of that, the total edge weights of the two trees are equal, and both are valid minimum spanning trees.

Now change one number: if that second edge had weighed 3 instead of matching the first edge's weight, the second tree would no longer be a minimum spanning tree — only the tree containing the lighter edge (weight ) would be the MST. In other words, the tie is exactly what lets two different trees share the minimum total weight. With pairwise distinct edge weights, you can never produce two different MSTs: the same minimum total can only be achieved by one edge set.

Sense-check: MST1 and MST2 have identical totals because the swapped edges have identical weights — swapping equal weights cannot change a sum. When the swap is unequal, the cheaper tree wins outright.

11.3.5 Student Questions and Answers

Q: Can there be more than one minimum spanning tree for the same graph? A: Yes. But if the weights of all the edges are pairwise distinct, then there can be only a single minimum spanning tree. The keyword in the statement is "pairwise distinct".

Q: Even when the edge weights are unique, multiple spanning trees are possible — for example one edge of weight 1 in one MST and some other edge of weight 1 in another — so how can the MST still be unique? A: The catch is the word pairwise distinct. It is possible for one MST to contain an edge of weight 1 while another MST contains a different edge of weight 1; in that case both trees are minimum spanning trees. Only when the weights of all the edges of the graph are pairwise distinct — no two edges anywhere sharing a weight — do we get exactly one minimum spanning tree.

Recap + bridge: an MST is a spanning tree of minimum total weight, and its uniqueness hangs entirely on whether all edge weights are pairwise distinct. Both greedy algorithms coming next always return an optimal tree — the question is how each one finds it.

11.4 Prim's Algorithm

11.4.1 The Greedy Idea

Two algorithms construct a minimum spanning tree from a given graph: Prim's algorithm and Kruskal's algorithm. Both solve the same problem, and both use the greedy strategy, but they apply the greedy idea in two different ways — and both always yield the optimal solution. Greedy strategies apply to optimization problems; the change-making problem and the fractional knapsack problem were the earlier examples, and minimum spanning tree construction is another one.

Purpose: Prim's algorithm builds a minimum spanning tree by growing a single tree. It starts from one source vertex and, at every step, adds the cheapest edge that connects the growing tree to a vertex outside it. During the entire process, the selected edges always form a connected tree — never a forest.

Inputs and outputs: the input is a connected, undirected, weighted graph with vertices, edges, and edge weights , plus a starting vertex (the source). The output is a set of edges forming an MST.

Intuition — the greedy question at each step: "which is the cheapest edge that touches my tree and reaches a vertex I have not reached yet?" Take that edge, add the new vertex, and ask again. Because the answer only ever connects new ground, the growing set of edges stays a single connected tree the whole time.

Steps of Prim's algorithm (high level):

  1. Start with the chosen source vertex; the tree contains only this vertex.
  2. Look at every edge leaving any vertex already in the tree.
  3. Pick the edge with the smallest weight that leads to a vertex not yet in the tree; add both the edge and the vertex to the tree.
  4. Repeat steps 2–3 until all vertices are in the tree.

The algorithm body is the same as Dijkstra's with one difference that matters: Prim's never adds up costs. Each decision uses only the single edge weight at that moment.

11.4.2 Worked Example 1 — Nine-Vertex Graph

Consider the given graph (think of it as a complete routing network) with vertices A, B, C, D, E, F, G, H, I. Start from vertex A.

Worked example — Prim's on the nine-vertex graph.

  • From A there are two edges: A–B and A–H. The least-cost edge from A is A–B, so A–B is the first edge added to the MST.
  • What is the second edge? The vertices now under consideration are A and B together — not just the last vertex B. Consider all outgoing edges from A and from B, and pick the shortest. Both B–C and A–H qualify, because they carry the same weight, so either can be picked; the total edge weight will not change, since the two edges are equal. The lecture's walkthrough picks B–C.
  • Next step: consider all outgoing edges from A, B, C and pick the shortest — that is C–I (weight 2).
  • Then consider all outgoing edges from A, B, C, I: the shortest is C–F (weight 2).
  • Then from A, B, C, I, F: the shortest is G–F (weight 2).
  • Then from A, B, C, I, F, G: the shortest is G–H.
  • Then from A, B, C, I, F, G, H: the shortest outgoing edge is C–D.
  • After C–D, the next shortest outgoing edge is from D: D–E.

The MST is complete: the selected edges are A–B, B–C, C–I, C–F, G–F, G–H, C–D, D–E — eight edges for nine vertices, one per vertex added, with no cycle ever formed.

Sense-check: every added edge attaches one new vertex to the growing tree (A→B→C→I, F, G, H, D, E), the partial result stayed a connected tree at every step, and the edges total fewer than the graph's edge count.

Two points deserve special attention. First, the cycle rule: even when an unchosen edge is cheap, if it connects two vertices that are already inside the tree, adding it would create a cycle, so it is skipped. At the later stages of this example the edge G–I (weight 6) was available but not picked for exactly that reason; instead C–D was picked. Second, the same logic covers a hypothetical A–H: if A–H were the shortest candidate at that stage (say its weight were 6), we would still not pick it, because we are building a minimum spanning tree, not a minimum spanning subgraph — a tree cannot contain a cycle, and A and H are already connected inside the tree.

Q: Why is the second edge B–C and not A–H? A: The vertices under consideration are A and B together, not only the last vertex B. Consider all outgoing edges from every vertex already in the tree and pick the shortest. B–C and A–H both qualify and either can be picked; the total edge weight will not change, because both edges carry the same weight. Considering only the outgoing edges of the last visited vertex is one mistake most students make.

Q: If the shortest outgoing edge turned out to be A–H (assume its weight is 6), would you pick it? A: No. We are constructing a minimum spanning tree, not a minimum spanning subgraph — a tree cannot contain a cycle. Both A and H are already inside the tree, so adding A–H would close a loop. This is the same reason the edge G–I (weight 6) was skipped even though it had not been picked.

Pitfalls:

  • Looking only at the outgoing edges of the last vertex added. When a new vertex joins the tree, all old vertices must be reconsidered for outgoing edges.
  • Picking a cheap edge whose two endpoints are already inside the tree — that creates a cycle. The MST is a tree, not a subgraph.
  • Forgetting that the partial result must stay connected: Prim's is a tree-growing algorithm, so at every intermediate step the chosen edges must form one connected piece.

11.4.3 Worked Example 2 — Six-Vertex Graph

A second graph on vertices A, B, C, D, E, F was solved live. Start from A.

Worked example — Prim's on the six-vertex graph.

  • A–B (weight 3).
  • B–C (weight 1).
  • C–F would also be correct here, but B–F (weight 2, the same as C–F) was picked deliberately, to make the point that the chosen edge does not have to leave the most recently added vertex — it can leave any vertex already in the tree.
  • F–E (weight 4).
  • Finally, the remaining vertex D must be connected: A–F is not under consideration, because A and F are both already in the tree and A–F would create a cycle; the edge must be F–D (weight 5).

All six vertices are now covered: A, B, C, D, E, F. The MST total edge weight is 15: the weights sum as , , , — equivalently .

Sense-check: five edges join six vertices with no cycle; every edge attaches a new vertex; and the total matches the lecture's stated 15.

Q: Why don't we just take the edges A–B, B–C, C–D in a row? A: Because adding C–D on top of the already chosen edges would create a cycle — B, C, D, F would form a loop with the B–F edge already in the tree. A tree must remain cycle-free.

Q: If we consider the edge C–F instead of B–F, will the tree still be correct? A: Yes. C–F also produces a minimum spanning tree with the same total weight, because B–F and C–F have the same weight; either choice gives a total of 15.

11.4.4 Prim's Algorithm and Dijkstra's Algorithm

Prim's algorithm closely resembles Dijkstra's algorithm: we start from a source, relax the edges, and pick the next vertex based on the lowest weight — looking at candidate weights 3, 5, 6, we take the 3, then keep exploring from the minimum-distance vertex. The algorithm bodies are nearly identical; the single difference is that Dijkstra adds the accumulated cost as it proceeds, while Prim's does not. Prim's considers only the individual edge weight at one particular time — no accumulated path cost is involved. The rectangular-box procedure shared by both algorithms (the first few statements of the pseudocode) is called initialize single source.

Q: Isn't Prim's algorithm similar to Dijkstra's algorithm? A: Yes. We start from a source, relax the edges, and pick the next vertex based on the lowest weight, then continue exploring from the minimum-distance vertex. The whole part is the same as Dijkstra's, except that we do not add the costs as we move ahead — only the individual edge weight matters at each step, not the accumulated path cost. Conceptually there is only this slight difference.

Q: What is the name of the rectangular-box procedure shared with Dijkstra's algorithm? A: Initialize single source. Because this part is identical to Dijkstra's algorithm — the first few statements of the pseudocode, before any edge is relaxed — the analysis carries over unchanged.

11.4.5 Time Complexity

Since the procedure is the same as Dijkstra's, the time complexity analysis is the same as Dijkstra's:

where is the number of edges and is the number of vertices (stated in the session as with edges and vertices). The steps: first construct a heap, then repeatedly extract the minimum from the heap — each extract-min costs , and the heap operations over all vertices and edges give . The detailed analysis was covered in the previous session and is not repeated here.

Recap + bridge: Prim's grows one connected tree by repeatedly taking the cheapest edge from any tree vertex to an outside vertex; it looks like Dijkstra's but adds no accumulated costs, and it runs in . Kruskal's solves the same problem with a different greedy move — sort the edges and never close a cycle.

Real-world connection: Prim's algorithm is the classic engine for designing low-cost networks — connecting campuses with cable, linking telephone exchanges, or wiring the pins of a circuit board. In any setting where a designer must connect every point of a network at minimum total cost, the cheapest connected structure is exactly the MST that Prim's produces.

11.5 Kruskal's Algorithm

11.5.1 The Greedy Idea

Kruskal's algorithm does the same job — building a minimum spanning tree — but the greedy application is different. Nobody gives a starting point; there is no source vertex. Instead we start from the edge with the minimum weight in the whole graph, and then keep adding the next shortest edge, with one condition: the added edge must not create a cycle. The only concept: sort the edges in ascending order of weight, pick the lowest-weight edge, and keep adding edges to the MST, until all the vertices have been connected.

Purpose: Kruskal's builds an MST from the edges outward. It never chooses a starting vertex — the smallest edge of the whole graph is the natural starting point, and every subsequent step takes the cheapest remaining edge that can still be added safely.

Inputs and outputs: the input is a connected, undirected, weighted graph with vertices and edges. The output is a set of edges forming an MST.

Intuition: imagine a landowner buying up the cheapest connecting roads one by one, always refusing any road that would close a loop. The roads bought never need to join into one connected piece while the purchase list is growing — only at the end must they connect everything.

Steps of Kruskal's algorithm (high level):

  1. Sort all edges of the graph in ascending order of weight.
  2. Take the lowest-weight edge. If adding it does not create a cycle, add it to the MST; if it would create a cycle, skip it.
  3. Repeat with the next-lowest edge until all vertices are connected (the MST has edges).

The key freedom: during the process, the selected edges need not be connected. They can form a forest — several separate trees growing independently — and only at the end must the result merge into a single tree. In Prim's algorithm the partial result is always a tree; in Kruskal's it can be a forest.

Scope: Kruskal's assumes a connected, undirected, weighted graph, just like Prim's. The cycle check is the heart of the algorithm: an edge that joins two vertices already linked through the current forest must be rejected, because the forest must stay acyclic to remain extendable to a tree.

11.5.2 Worked Example 1 — Nine-Vertex Graph

The same nine-vertex graph (A, B, C, D, E, F, G, H, I) is solved with Kruskal's algorithm:

Worked example — Kruskal's on the nine-vertex graph.

  • The minimum-weight edge in the whole graph is H–G (weight 1); that is the starting point.
  • The next edge: G–F (weight 2) or C–I (weight 2). In the walkthrough C–I was picked first.
  • The class was then asked for the next edge and the answer came back A–B or C–F — but all of us forgot about G–F, which also has weight 2 and creates no cycle. So the correct next edge is G–F. The mistake was corrected on the spot: "I made the mistake of saying that it is A–B or C–F. But it is G–F."
  • After G–F, it can be C–F or A–B (the same weight); A–B was added.
  • Next, C–F is added — it also creates no cycle. As long as no cycle is created, we add edges, because we have to connect all the vertices at minimum cost.
  • The next candidate by weight is I–G (weight 6), but I–G would create a cycle, so it is skipped; instead C–D is added.
  • The next shortest edge is I–H (weight 7), which also creates a cycle, so it is skipped; the final edge D–E is added.

The MST edges are H–G, C–I, G–F, A–B, C–F, C–D, D–E — seven edges for nine vertices. (The weights of C–D and D–E were not stated in the discussion; the run only needs them to be the next-lowest edges that create no cycle.)

Sense-check: the process ends with a connected tree even though intermediate stages were forests; two weight-2 edges (I–G weight 6, I–H weight 7) were rejected precisely because each would have closed a cycle.

11.5.3 Worked Example 2 — Six-Vertex Graph

The same six-vertex graph (A, B, C, D, E, F) is solved again with Kruskal's:

Worked example — Kruskal's on the six-vertex graph.

  • First stage: B–C (weight 1) — the smallest edge.
  • Next: F–E (weight 4). By adding F–E the two selected edges are disconnected — a forest — and that is perfectly fine for Kruskal's.
  • Next: A–B (weight 3).
  • Next: B–F or C–F? C–F (weight 2) was added this time; it resolves the doubt left over from the Prim's run, where B–F was chosen instead.
  • Next: F–D (weight 5), which connects the last vertex.

The total weight of this MST is the same 15: .

Sense-check: five edges join six vertices with no cycle; the total matches the lecture's stated 15 — the same minimum total that Prim's found on the same graph, even though the edge sets differ.

Prim's and Kruskal's can create two different MSTs for the same graph — different structure, different edge sets — but the minimum total weight is the same, because both algorithms always return the optimal solution.

11.5.4 Time Complexity

The analysis again uses a heap. There are edges, so the heap construction time is , and each extract-min takes ; extracting every edge once gives

which is the same complexity as

since and differ by at most a constant factor on connected graphs (, so ). The concept difference from Prim's is only that Kruskal works on edges instead of vertices; the analysis pattern is identical to Dijkstra's, so the details from the previous session carry over.

11.5.5 Student Questions and Answers

Q: Why can't G–F be part of the minimum spanning tree? It has weight 2, the same as C–I. A: It can be — it must be. That answer was a mistake: the next edge was said to be A–B or C–F, but G–F was forgotten. G–F has weight 2 and its addition creates no cycle, so it is the correct next edge and must be picked. After G–F, the remaining choices are C–F or A–B, which share the same weight.

Q: What is the cloud concept used in the textbook explanation of Kruskal's algorithm? A: A cloud is just a way of picturing the edges already visited and merged. Cormen's textbook explains Kruskal's by treating each tree of the growing forest as a cloud: "merge cloud V and cloud U" means take the newly selected edge and merge it with the already selected edges. Do not let the word cloud confuse you — you can think of it as visited and non-visited vertices.

Recap + bridge: Kruskal's sorts the edges, takes the lowest-weight edge that creates no cycle, and is allowed to be a forest until the end; it runs in . Prim's and Kruskal's give the same optimal total weight on the same graph — next we compare them directly.

Real-world connection: Kruskal's is the natural algorithm when edges come pre-priced as a list — leasing telephone lines between city pairs, or selecting transmission links from a tariff sheet. Because it works from the sorted edge list, it also pairs well with database-style sorting and union-find bookkeeping at scale.

11.6 Prim's vs Kruskal's — When to Use Which

11.6.1 Sparse and Dense Graphs

The choice between the two algorithms depends on the graph. Kruskal's algorithm is the right choice when the graph is sparse — when it has few edges — because all of Kruskal's operations are based on edges. Prim's algorithm is the right choice when the graph is very dense — when it has many edges — because Prim's is vertex based. In short: Kruskal's is edge based, Prim's is vertex based.

Intuition: Kruskal's spends its work on the edge list — sorting it and scanning it — so a graph with few edges is its natural home. Prim's spends its work on vertices and their neighborhoods, so it thrives when the graph is so dense that edge-based sorting becomes the bottleneck.

11.6.2 Side-by-Side Comparison

Property Prim's algorithm Kruskal's algorithm
Starting point Any vertex (a source is chosen) The minimum-weight edge; no source given
Edge selection Shortest edge connected to any vertex already in the tree Next shortest edge that does not create a cycle
Shape during the process Always a tree (connected) May be a forest (disconnected trees)
Final result Minimum spanning tree Minimum spanning tree
Basis Vertex based Edge based
Best for Dense graphs Sparse graphs

The rules to remember: Kruskal's selects the shortest edge, then the next shortest edge that does not create a cycle, and repeats until all the vertices have been connected; it begins with a forest and merges into a tree. Prim's selects any vertex, then repeatedly selects the shortest edge connected to that vertex — connected to any vertex already in the tree — and stays a tree the whole time. The common student mistake in Prim's is thinking only about the outgoing edges of the last vertex visited; when a new vertex is added, the old vertices must also be reconsidered for outgoing edges.

When to pick which: if the graph is sparse, pick Kruskal's (edge based); if the graph is dense, pick Prim's (vertex based). Both deliver the same optimal total weight, so the choice is about which data the algorithm leans on.

11.7 Applications of Minimum Spanning Trees

11.7.1 Communication and Transportation Networks

Real-world: a phone company leases lines to connect cities; the company charges different amounts of money to connect different pairs of cities. We want a set of lines that connects all our offices (all the cities) with minimum total cost — that is exactly an MST. The same idea covers laying communication cables to connect every building within a campus, or connecting telephone networks. In transportation planning, from a common hub city, what is the minimum-distance way to reach several destination cities (for example from Bangalore to Hyderabad, to Chennai, to other places)? An MST gives the cheapest connected structure.

Why MSTs appear everywhere in networking: any time the goal is "connect all the points, spend the least total money or distance," the answer is the minimum spanning tree — the unique (or tied) cheapest way to make everything reachable without redundant links.

11.7.2 Cluster Analysis

Real-world: the K-means algorithm (the K-clustering problem) can be viewed through MSTs. Clustering groups similar points: we want minimum intra-cluster distance (points inside one cluster should be close) and maximum inter-cluster distance (different clusters should be far apart). One way to do this: find the MST of the points, then delete the most expensive edges. Each deletion splits one cluster into two, and after deletions we have clusters. If we can define a distance limit, every edge within that limit forms a cluster. Students who already know clustering from machine learning or data mining will appreciate this angle; it requires thinking a little out of the box.

Worked idea — clustering with the MST: suppose ten data points are nodes of a complete graph whose edge weights are distances. Build the MST (10 points, 9 edges), then remove the 2 most expensive edges for : the tree splits into 3 connected pieces, each piece is one cluster. The most expensive removed edges are exactly the gaps between clusters — the largest intra-group distances, whose removal maximizes inter-cluster separation.

11.7.3 Image Registration and Segmentation

Real-world: image segmentation is the process of partitioning an image into different components, with the purpose of decomposing the image into significant regions. To extract a specific object — say, to find the cat in a picture — we first define properties of the cat, then decompose the image into only the relevant parts, separating significant areas from non-significant areas. We can think of this as connecting dots between the significant areas: all the homogeneous areas get connected inside our spanning tree, and everything else falls outside the tree, so the disconnected parts are segmented out. Image registration uses the same idea: aligning two images of the same scene by matching their significant structures through a spanning tree. This short explanation is only a hint; a full appreciation requires reading about the technique in detail.

11.7.4 Taxonomy and Feature Extraction

Real-world: taxonomy — the science of classification — fits the same picture: related parts get connected, disconnected parts are unrelated, so a taxonomy of organisms or documents can be laid out as a tree of relations. Real-world: feature extraction (the features used in data mining and machine learning) can be seen from the same angle: a minimum spanning tree over feature vectors connects the most similar features and leaves dissimilar ones apart, which supports dimensionality reduction and feature selection. These connections only make full sense to students who already know clustering and feature extraction; they are listed as applications of the MST and can be read in detail when there is time and interest.

Where this matters: the MST is not an abstract exercise — it is the mathematical core of network design, clustering, image analysis, and classification. Any problem that asks for "the cheapest way to connect everything" or "the natural grouping of similar things" can often be re-read as an MST problem.

11.8 Exam-Style Problem — Which Algorithm Produced This Partial Spanning Tree?

11.8.1 The Question

A practice document contains an exam question from another institution that is very relevant — a different version of the same question appeared in our own exam, because it proves in depth whether both algorithms are understood. The question: each figure below represents a partial spanning tree. Determine whether it could possibly come from a prematurely stopped Prim's algorithm or a prematurely stopped Kruskal's algorithm, both, or neither. There are six or seven graphs, and the answer key is given at the end of the document.

The whole catch is the phrase "prematurely stopped": the algorithm was stopped in the middle of its run, so what you see is an intermediate stage — not the finished MST.

Exam note: without explanation, the answer earns nothing — writing "Prim's" or "Kruskal's" and moving to the next question gets zero marks, because the examiner cannot tell whether the answer came from understanding or from guessing.

11.8.2 Worked Analysis — Graph 1 (Kruskal's)

Worked analysis — Graph 1.

The first figure is Kruskal's, and the reason is easy: the selected (bold) edges are disconnected. Kruskal's is allowed to be a forest in between; Prim's is always connected. So the partial tree must come from Kruskal's.

Sense-check: a disconnected partial tree can only be Kruskal's, because Prim's never produces a disconnected intermediate stage — its selected edges always form one connected tree.

11.8.3 Worked Analysis — Graph 2 (Prim's only)

Worked analysis — Graph 2.

The second figure is Prim's only — not Kruskal's, not both. To see that it is not Kruskal's, trace Kruskal's algorithm on the graph: it would first select the edge of weight 1, then the edge of weight 2, then an edge of weight 3, then the other edge of weight 3, then the weight-4 edge, then weight 6, then weight 8 — skipping weight 7 because it would create a cycle — and then it would select the weight-13 edge. But in the figure the 13-edge is not selected; instead a 14-edge is selected. Since Kruskal's, run from the start, would definitely have selected that 13-edge before any 14-edge, the figure cannot be a prematurely stopped Kruskal's run.

This conclusion was not possible at one glance — the check required tracing the algorithm. Then verify the figure against Prim's by the same method: run Prim's algorithm on the graph and compare the result at some stage with the figure; the stages match, so the answer is Prim's only.

Sense-check: the trace of Kruskal's is forced (edges are always taken in sorted order, cycle-free), so its intermediate edge sets are predictable; when the figure's edge set contradicts the forced order, Kruskal's is ruled out — and a matching Prim's stage then closes the case.

11.8.4 Student Questions and Answers

Q: In the second graph, the weight-13 edge is not selected — the vertex is not visited — so what happens? A: Read the question very carefully: the algorithm was prematurely stopped. The run was halted in between, so what you are seeing is a stage during the process, not the final result. The 13-edge would have been selected later if the run had continued.

11.8.5 Practice Guidance

Exam note: many students will miss the word "prematurely stopped" in the exam and mess up the whole answer — read the question very carefully.

Some of the remaining figures have "both" and "neither" as the correct answers, which is the real catch. When the selected edges could plausibly come from either algorithm at some stage, the answer is "both"; when the edge set could not arise from either algorithm at any stage, the answer is "neither". Notice that a connected partial tree is not automatically Prim's — Kruskal's can be connected at an intermediate stage too — and a disconnected one is not automatically Kruskal's answer territory for "neither", because both algorithms must actually be traceable to that exact stage.

Exam note: this is not rocket science, but it needs patience — run both algorithms on each graph and compare stages. Practice all the graphs at home before the exam, including the "both" and "neither" cases.

11.9 Dynamic Programming — Foundations

11.9.1 The Name and the History

Dynamic programming is the third (and last) design strategy of the course. It was invented by the mathematician Richard Bellman. The word "programming" in the name of the technique stands for planning — it does not refer to computer programming. Dynamic programming is dynamic planning; the name is a misnomer and should not be confused with writing programs.

Why the name matters: "programming" here comes from the older use of the word, meaning planning and decision-making over time (the same sense as in "linear programming"). So dynamic programming really means "planning a sequence of decisions," not "writing code" — a student who reads the name literally will go looking for the wrong idea.

11.9.2 Overlapping Subproblems

Dynamic programming is a technique for solving problems with overlapping subproblems — overlapping subproblems, very, very important. A typical problem's solution can be related to the solutions of its smaller subproblems. The difference from divide and conquer: in divide and conquer, we divide a problem of size into subproblems of size , solve the subproblems individually, then combine their solutions into the solution of the original problem. In dynamic programming, the subproblems are not independent — they overlap. So rather than solving the same subproblem again and again, dynamic programming solves each smaller subproblem only once and records the result.

Why is that possible? Because the subproblems overlap: when the same subproblem shows up again during the solution of the main problem, we do not re-solve it — we use the stored solution.

Intuition: a student revising for an exam has three overlapping topics; once the notes for a topic are made, they are reused every time that topic appears in a practice paper, instead of rewriting the notes each time. Dynamic programming is exactly that: compute a subproblem once, save the answer, reuse it.

Core idea of dynamic programming: solve every distinct subproblem exactly once, store its solution, and look it up whenever the same subproblem reappears.

11.9.3 Dynamic Programming vs Divide and Conquer

The contrast with divide and conquer: there, subproblems are solved independently and their solutions combined. Here, since subproblems overlap, the first encounter solves the subproblem and stores the result; the second encounter reuses the stored solution. That single difference — solving each subproblem once and storing it — is the entire idea of dynamic programming.

Property Divide and conquer Dynamic programming
How the problem is split Into independent halves (size ) Into subproblems that overlap
Subproblems Independent Shared / repeated
Second encounter of a subproblem Solved again from scratch Stored solution reused
Typical examples Merge sort, binary search Fibonacci, 0/1 knapsack

11.9.4 The Space-Time Trade-off

The moment we say "store the result," there is a space-time trade-off. We save time by not re-solving overlapping subproblems, but storing results costs extra space. These days space is much less of a concern; if we can take advantage of time, the space cost is acceptable. A straightforward application of dynamic programming can be interpreted as a special variety of the space-for-time trade-off — it is an optimization of plain recursion.

Trade-off in one line: dynamic programming buys speed with memory — it pays for fast solutions by holding every computed subproblem answer, and the bigger the saved recomputation, the better the deal.

Recap + bridge: dynamic programming is planning, not coding; it targets problems with overlapping subproblems, solving each once and storing it — the opposite of divide and conquer. The space-for-time deal is the price of admission, and Fibonacci is the simplest place to see the payoff.

11.10 Fibonacci — The First Dynamic Programming Example

11.10.1 The Plain Recursive Version

The simplest example is the Fibonacci numbers. The plain recursive algorithm, written as a recurrence: for , if , return ; otherwise return :

A problem of size is divided into two subproblems of sizes and — note it is not divided into or ; the split is by subtraction, not halving. That detail matters: the two subproblems overlap, because itself contains an call.

11.10.2 Overlapping Subproblems in the Recursion Tree

Take , a very small number. The recursion expands as ; then expands as , and expands as . Already the subproblems repeat: appears twice, appears twice, appears twice. For such a small input, overlapping subproblems are already all over the tree. The recursion stops when , so and do not need recursion. The problem definitely has overlapping subproblems.

Worked example — the F(5) recursion tree.

The tree, one level at a time:

Counting the calls: is computed twice, is computed twice, and is computed twice. Even at — a tiny input — the same subproblem appears in multiple branches.

Sense-check: the repeated , , and calls are exactly the overlap that dynamic programming exploits: compute each once, reuse the stored value.

11.10.3 Time Complexity of Plain Recursion

The plain recursion solves the same subproblems over and over. A problem of size splits into size plus size ; each of those splits further — note that itself splits into and — so the recursion tree is exponential:

which we cannot afford. Every level of the tree doubles the number of calls (roughly), so the number of leaf calls grows like — the same function that measures how fast bacteria colonies double.

11.10.4 The Iterative Dynamic Programming Version

The dynamic programming version is the simple iterative Fibonacci that most students have written many times without knowing it is dynamic programming: store in an array that fills from left to right, in increasing order. When is needed again, it is already stored — no recomputation. The time complexity is : linear, down from exponential. Storing the results in a simple array turns into . This is the basic concept of dynamic programming — that is all it is.

The professor's warning: if, by looking at this algorithm, you cannot say the time complexity is linear, that should come naturally — you would have to start from the beginning of the course, because reading a loop and stating its linear complexity should be a default reflex.

11.10.5 Optimal Substructure

The term optimal substructure: a problem can be solved by using the solutions of its subproblems — it has optimal substructure. This term was already studied during the greedy method. In Fibonacci's case, the value is defined directly in terms of and — the solution of the subproblem is literally part of the original solution. Where the greedy method used optimal substructure to justify the greedy choice, dynamic programming uses it to justify building up from small subproblems.

11.10.6 Student Questions and Answers

Q: Does computing Fibonacci numbers have overlapping subproblems? A: Yes — that is exactly what makes Fibonacci the first dynamic programming candidate. The iterative Fibonacci is the dynamic programming version of the same computation.

Q: Why does a recursive Fibonacci with an LRU cache not fall into this discussion? A: This course's analysis is independent of implementation. The strategy decision is made before you go near a computer, so implementation details such as caching are not considered during the analysis. The point of the exercise is choosing the right method for the scenario — plain recursion is exponential, dynamic programming is linear.

11.10.7 Worked Word Problem — Rabbits and the Fibonacci Series

Exam note: do not expect an exam question to literally say "Fibonacci series" — word problems are framed differently, and the skill being tested is recognizing the pattern.

The example used: a man puts a pair of rabbits in a place surrounded by a wall. How many pairs of rabbits will there be in a year, if the initial pair of rabbits are newborn, and all rabbit pairs are not fertile during their first month? (A disclaimer came with the story: the scenario is not realistic — it is a cooked-up question, not one that appeared in the exam, but it shows how Fibonacci gets framed.)

Worked example — the rabbit problem, month by month.

The catch is the fertility rule: the newborns are not fertile during their first month, and each fertile pair gives birth to one new male-female pair at the end of every month.

  • — at the start, zero pairs (the newborn pair is counted from month 1).
  • — during the first month there is only the one pair.
  • — during the second month there is still only one pair, because the original pair gives birth only at the end of the month.
  • — during the third month, the original pair has produced one new pair.
  • — during the fourth month, only the first pair is fertile (the second pair is newborn and not fertile in its first month), so one new pair joins: three pairs.
  • — by the fifth month, both the first and second pairs are fertile, the third is not: five pairs.

The sequence continues as the Fibonacci series, and at the end of the year — — there are 144 pairs.

Sense-check: the counts 0, 1, 1, 2, 3, 5 follow the rule "this month = last month + the month before" — the same recurrence as , and closes the year.

The full solution was written out; anyone who did not follow was asked to read the question again, since the scenario itself is simple.

Exam note: the same framing trick applies to other problems — the statement hides the pattern, and you must find it.

11.11 The General Dynamic Programming Technique

11.11.1 When Dynamic Programming Applies

Dynamic programming applies to a problem that at first seems to require a lot of time — possibly exponential — provided we have simple subproblems. The requirements:

  1. Simple subproblems. The subproblem can be defined in terms of a few variables.
  2. Subproblem optimality. The global optimum value can be defined in terms of optimal subproblems. In simple terms: once you solve a subproblem, the solution of that subproblem should help you solve the original problem. It must not be the case that you solve a subproblem and that subproblem's solution is not even present in the solution of the original problem. That will happen in some cases — the knapsack problem shows it.
  3. Subproblem overlap. The subproblems are not independent. In divide and conquer, subproblems are independent; in dynamic programming they overlap.
  4. Build bottom-up. Solve the smallest subproblem first, then the next, then the next, going up.

Intuition — why all four conditions matter: the technique is a deal. Condition 1 keeps the bookkeeping cheap (a few variables per subproblem); condition 2 guarantees the stored answers are actually useful for the final answer; condition 3 guarantees the store is used more than once (otherwise the storage is wasted); condition 4 gives a simple, safe order to fill the store in.

Assumption: subproblem optimality is a requirement that must be checked, not a fact. The lecture's warning is direct: "It should not be the case that you solve a subproblem, but that subproblem solution is not even present in the solution of the original problem. That should not happen. That will happen in some cases." The 0/1 knapsack is the case study where the naive version of the condition fails — and the remedy is a cleverer subproblem definition, seen next.

11.11.2 Bottom-Up Construction

The construction order is bottom-up: solve the smallest subproblem first, then the next larger one, and so on, until the original problem is solved. Each step reuses the stored solutions of the smaller subproblems. The first algorithm studied under this technique is the 0/1 knapsack problem.

Recap + bridge: four conditions — few variables, subproblem optimality, overlap, bottom-up order — define when dynamic programming is the right tool. The 0/1 knapsack is the first real algorithm built on these rules, and it will test all of them.

11.12 The 0/1 Knapsack Problem

11.12.1 Problem Statement

We are given a set of items, where each item has a weight and a profit , and a knapsack of capacity . We must choose items so that the total profit is maximized, subject to the total weight being at most the knapsack's capacity.

Hook: a thief with a backpack of limited capacity faces a wall of valuables. Each item is indivisible, and every item has a weight and a value. Which subset maximizes the loot without breaking the bag? That is the 0/1 knapsack problem — and with items the naive "try everything" approach grows out of control almost instantly.

11.12.2 0/1 vs Fractional Knapsack

The fractional knapsack problem falls under the greedy method; the 0/1 knapsack problem falls under dynamic programming — the most effective way of solving each problem is with its respective design strategy. The difference: in 0/1 knapsack, each item must be entirely accepted or entirely rejected. Fractional knapsack allowed dividing an object into fractions; that flexibility does not exist here. If you take an object, you take it completely; if you do not, you leave it completely.

Intuition — why greedy fails here: in the fractional version, taking the item with the best value-per-kilogram always works because leftover space can be filled with a fraction of the next item. In the 0/1 version that escape hatch is gone: the best value-per-kilogram item may fill the bag awkwardly and block a better combination, so a greedy rule cannot be trusted.

11.12.3 Mathematical Formulation

With indicating whether item is taken, the problem is:

where is the profit of item , is its weight, and is the knapsack capacity. The decision variable is always 0 or 1; the total weight must be less than or equal to the capacity. That is the difference between 0/1 and fractional knapsack.

11.12.4 Worked Example — Choosing Items by Hand

Q: Is "width" related to "weight" in the knapsack problem statement? A: No. Width is not related to weight. It is a typo in the problem statement — treat it as the weight the knapsack can hold (9 kg in the example).

Five items are given, each with a weight and a profit. The knapsack can hold 9 kg. The chosen solution: item 5, at 2 kg, gives a profit of 80; item 3, taken completely, is 2 kg and gives a profit of 6; item 4, taken completely, is 4 kg and gives a profit of 20.

Worked example — the hand-picked solution.

  • Item 5: weight 2 kg, profit 80.
  • Item 3: weight 2 kg, profit 6.
  • Item 4: weight 4 kg, profit 20.

Total weight used: kg, which is within the 9 kg capacity. Total profit: 106.

Sense-check: 8 kg ≤ 9 kg capacity, and the profit 106 beats any other visible subset of the five items — but notice how long even this small search took by eye. This example shows why we need an algorithm: with hardly five items, thinking and guessing took a long time — with many items, trial and error fails.

11.12.5 Brute Force — 2^n Combinations

For items, the brute force approach enumerates every possible combination: for each item, either select it or do not. With four items, that is combinations, ranging from 0000 (select none) to 1111 (select all) — not (four factorial), because the order of selection does not matter and each item is independently in or out. In general there are possibilities.

Worked example — counting the combinations.

With four items, each item contributes an independent binary choice: 0 (leave) or 1 (take). The sixteen combinations run from 0000 (nothing taken) through 1000, 0100, 0010, 0001, 1100, ... up to 1111 (everything taken). That is 16 possibilities — not , because order is irrelevant.

Sense-check: the multiplication principle (2 choices per item, 4 items) gives , and the same reasoning for items gives .

Not all combinations may be applicable — the weight constraint eliminates some — but in the worst case (for example, if every item's weight is small enough to fit), brute force must consider all , which is exponential.

Q: Is the number of possible combinations four factorial? A: No. With four objects, each object is either selected or not: select none, select only the first, only the second, the first and second together, and so on up to selecting all. That gives 2 to the power 4 possibilities, in general — not factorial.

11.12.6 Building the Dynamic Programming Table

The example: capacity , and 4 objects with profits 1, 2, 5, 6 and weights 2, 3, 4, 5 respectively:

Object Weight Profit
1 2 1
2 3 2
3 4 5
4 5 6

Build a table with rows for objects and columns for capacities : since the capacity is 8, there are 9 columns (numbered 0 to 8); since there are 4 objects, there are 5 rows (numbered 0 to 4). We start from zero — that is why there is a plus one on both counts. Whatever the capacity of the knapsack, that plus one is the number of columns; however many objects there are, that plus one is the number of rows. This matters for the algorithm: these counts are the loop bounds.

Fill the first row and the first column with 0 without thinking. In the first column, the assumption is a knapsack of capacity 0 — whatever objects are available, nothing fits, so the maximum profit is 0. In the first row, the assumption is zero objects — however large the capacity, the maximum profit obtainable from no objects is 0.

Worked example — filling the table, row by row.

  • Row 1 (only object 1: weight 2, profit 1): at capacity 1, the object does not fit, profit 0. At capacity 2, it fits, profit 1. At capacity 3 and above, the maximum profit is still 1, because only this one object exists; increasing the capacity does not create more profit.
  • Row 2 (objects 1 and 2): at capacity 1, nothing fits, 0. At capacity 2, object 1 fits, profit 1. At capacity 3, object 2 fits and gives profit 2, which beats object 1's 1, so 2. At capacity 4, both objects together weigh , which does not fit; the best single object is object 2, so 2. At capacity 5, both fit, profit . At capacity 6 and above, still 3 — the maximum with these two objects.
  • Row 3 (add object 3: weight 4, profit 5): at capacities 1, 2, 3, object 3 does not fit, so copy the values from row 2 (0, 1, 2). At capacity 4, object 3 fits exactly, and its profit 5 beats everything from row 2, so 5. At capacity 5, adding any other object to object 3 overshoots the capacity (), so the maximum stays 5. At capacity 6, object 3 plus object 1: weight , profit . At capacity 7, object 3 plus object 2: weight , profit . At capacity 8, object 3 plus object 2 still gives 7 (adding object 1 too would exceed 8), so 7.
  • Row 4 (add object 4: weight 5, profit 6): at capacity 8, either keep row 3's 7, or make room for object 4: remaining capacity , whose best value with objects 1–3 is 2, plus object 4's profit 6, giving . The maximum is 8.

The final table:

B(k, w) w = 0 1 2 3 4 5 6 7 8
k = 0 (no objects) 0 0 0 0 0 0 0 0 0
k = 1 (object 1) 0 0 1 1 1 1 1 1 1
k = 2 (objects 1–2) 0 0 1 2 2 3 3 3 3
k = 3 (objects 1–3) 0 0 1 2 5 5 6 7 7
k = 4 (objects 1–4) 0 0 1 2 5 6 6 7 8

The maximum profit obtainable is the bottom-right cell: 8.

Sense-check: the bottom-right cell always answers the original problem — all 4 objects available, full capacity 8. The value 8 comes from object 4 + object 2 (weight , profit ), exactly the combination the table says is best.

11.12.7 The B(k, w) Recurrence

The table is not filled by thinking case by case; it is filled by a formula. Let be the maximum profit obtainable from items with capacity . The recurrence:

where is the weight of the object under consideration and is its profit.

Case 1: when , the object under consideration does not even fit, so the maximum value of the knapsack with items at capacity is the same as the maximum value with items — the recurrence copies the value from the row above. For example, at : , so copy ; the same copy happens at and .

Case 2: when , compare two options: the best value without the object, , and the best value with it — make room by subtracting the object's weight, look up , then add the object's profit . Take whichever is larger. The worked cell was : here , so compute .

11.12.8 The Logic Behind the Recurrence

Logical reading of case 1: adding the new object cannot increase the value of the knapsack, because the object will not even fit — the maximum profit does not change, so we copy the previous row's value down.

Logical reading of case 2: when the new item can fit, we check whether including it increases the profit. Suppose object 1 is already in the knapsack. When considering object 2, first check whether its weight exceeds the capacity — if it does, there is no question of including it. If it fits, we must create space for it: subtract its weight from the capacity, look up the best profit for that remaining capacity using only the earlier objects (that is the term — the state of the knapsack without the new object), then add the new object's profit. Between the knapsack without the new object and the knapsack with it, keep whichever gives more profit.

Intuition (the professor's own): to include a new object you must first create space by subtracting its weight. When you find space for the new object, you must use the profit earned without the new object — that is exactly why the look-up is , the state of the knapsack before the new object joins — and only then add the new object's profit.

The worked numbers: when the capacity is 6, objects of weight 4 and 2 fit together (profit ); when the capacity is 7, objects 2 and 3 fit together (profit ); when the capacity is 8, the maximum is 8 (object 4 plus object 2: profit ).

Q: Can you explain the formula once more? (Understood. Didn't understand. Understood something. Didn't understand the word.) A: Compare the two options. Assume object 1 is already in the knapsack. When considering object 2, first check whether its weight exceeds the capacity — if it does, there is no question of including it, so copy the profit already got without it. If it fits, check whether including it raises the profit. To include it, create space first: subtract its weight from the capacity and take the best profit for that remaining capacity without the new object — that is the minus 1, minus term — then add the new object's profit. Pick the larger of the two: the knapsack without the new object, or the knapsack with it.

11.12.9 Subproblem Optimality — Where Knapsack Breaks the Rule

Exam note: the 0/1 knapsack fails the naive subproblem optimality test, and this is the case the general technique warned about ("that will happen in some cases").

Worked counterexample — the five-object case.

Consider five objects with (profit, weight) pairs (3, 2), (5, 4), (8, 5), (4, 3), (10, 9) and capacity 20.

  • With only the first four objects, the optimal solution includes the object (4, 3): the four-object optimum is the set (3, 2), (5, 4), (8, 5), (4, 3) — profit at weight .
  • With all five objects, the optimal solution is (3, 2), (5, 4), (8, 5), (10, 9) — profit at weight — and it does not contain the object (4, 3).

The optimal solution of the five-object problem does not contain the optimal solution of the four-object subproblem: (3,2), (5,4), (8,5), (4,3) is not a subset of (3,2), (5,4), (8,5), (10,9).

Sense-check: dropping the (4, 3) object frees 3 kg of capacity, which lets the (10, 9) item in and raises the profit from 20 to 26. The "optimal subproblem" was too greedy with the small capacity — this is exactly why the same-capacity subproblem definition fails.

That is exactly the reason for the subtraction : the recurrence looks up the best value for the remaining capacity — a different subproblem than the same-capacity one — which accommodates the dropped object.

Q: Why does the 0/1 knapsack fail the naive subproblem optimality test? A: With objects (3,2), (5,4), (8,5), (4,3), (10,9) and capacity 20: the optimal solution with four objects contains the object (4,3), but the optimal solution with all five objects does not contain it. The four-object optimum is not a subset of the five-object optimum. That is why we do the subtraction : we look up the best profit for the remaining capacity, a different subproblem than the same-capacity one.

11.12.10 Overlapping Subproblems in Knapsack

The knapsack problem does have overlapping subproblems. Consider 3 objects and capacity 2 (assume unit weight and unit profit for every object, for simplicity — other values work the same way). The decision for each object is include or exclude.

From the start — 3 objects, capacity 2 — the "exclude" branch keeps 2 objects at capacity 2, and the "include" branch has 2 objects at capacity 1. Each of those states branches again into include/exclude, and the same states reappear: a state with 1 object at capacity 1 appears in multiple places in the tree. With a small capacity of 2 this is already visible; with a capacity of 100, the tree fills with many repeated subproblems. Exploring every branch fully is exponential for sure — dynamic programming is what avoids the repeated work.

11.12.11 Time Complexity — O(nw) and Pseudo-Polynomial Time

The table method runs in time : the outer loop runs over the objects (0 to n) and the inner loop over the capacities (0 to w) — we simply fill an matrix. The algorithm is a line-by-line conversion of the table filling: if , apply one formula; otherwise apply the other; fill the complete matrix. (Tracking which objects were selected needs a few extra lines of code; the concept is only the table filling.) Brute force took in the worst case; the DP version runs in .

This type of algorithm is called a pseudo-polynomial time algorithm. Until now, every algorithm's time complexity was expressed in terms of the input size — the number of inputs, . Here another factor appears, and is a criterion within the problem statement, not the input size. The running time depends on the magnitude of a number given in the input, not its encoding size. (This connects to a note from the first session: the in the order of growth is not exactly the input size — it is the number of bits needed to encode the input.)

The professor's warning: if is very large — as large as, or bigger than, — the DP algorithm becomes slower than the brute force method. We have to live with this, because no better polynomial time algorithm is known for this problem; the nature of the problem itself is complex. This is why the algorithm is only "pseudo"-polynomial: its running time is not a function of the input size alone, and a huge capacity number makes the table enormous.

The next session continues the story: NP — non-deterministic polynomial time algorithms.

11.12.12 Reconstructing the Chosen Objects

The table gives the maximum profit, but which objects produce it? The trick — which may not be in the textbook — is tracing first appearances: the maximum profit sits in the last cell, the bottom-right corner, and profit values first appear in the row where the object that creates them is introduced.

Worked example — recovering the chosen objects.

  • Read the last cell: 8.
  • Find the first place in the matrix where 8 appears: row 4. So object 4 is included — otherwise the value 8 would not have appeared at row 4.
  • Object 4's profit is 6. Subtract: . We now need the object that contributes profit 2.
  • Find the first place in the matrix where 2 appears: row 2. So object 2 is included; its profit is 2.
  • Subtract again: , done.

The chosen objects are 4 and 2 — weight , within capacity 8, and profit .

Sense-check: the reconstructed set has exactly the same weight and profit as the bottom-right cell implies (weight 8, profit 8), and the walk stops exactly when the remaining profit hits zero.

General rule: whenever the last cell's value first appears in row , object is included; subtract its profit from the remaining amount and repeat.

Q: If the profit 2 does not appear anywhere in the matrix, what is the next step? A: That situation cannot occur: if there were no 2 anywhere, we would not have gotten in the first place. The subtraction exists because the included object's profit (6) accounts for part of the total 8 — the remainder must itself be a profit value that appeared when its contributing object was introduced.

Q: What if object 4 was not selected? A: Then the last cell would not contain a new value — the profit would have been copied down from an earlier row. In that case the maximum value would have appeared first in some other row, and the object introduced in that row is the one that is included.

Recap + bridge: the 0/1 knapsack is solved by the table in pseudo-polynomial time, and the chosen items are recovered by tracing where each profit value first appears. This is the full dynamic programming recipe in miniature — and the pseudo-polynomial wrinkle is the doorway to NP, the topic of the next session.

Exam Guidance Summary

  • MST question type: partial spanning tree figures — decide Prim's / Kruskal's / both / neither for a prematurely stopped run. A different version of this question appeared in the actual exam; it proves depth of understanding. Always explain the reasoning — answers without explanation earn zero marks. The word "prematurely stopped" is easy to miss; read the question carefully. Practice all the graphs, including the "both" and "neither" cases.
  • MST theory: a graph can have multiple MSTs; uniqueness holds only when all edge weights are pairwise distinct. Both Prim's and Kruskal's always give an optimal solution; the total weight is the same even when the tree structures differ.
  • Prim's: starts from any vertex; always a tree; pick the shortest edge connected to any vertex already in the tree (not just the last vertex). Analysis: O(E log V), same as Dijkstra's.
  • Kruskal's: starts from the minimum-weight edge; may be a forest during the process; pick the next shortest edge that does not create a cycle; ends as a tree. Analysis: O(E log E) = O(E log V).
  • Choice: Kruskal's for sparse graphs (edge based), Prim's for dense graphs (vertex based).
  • Dynamic programming: overlapping subproblems solved once each; space-time trade-off; optimal substructure; bottom-up construction.
  • Fibonacci: plain recursion is O(2^n); iterative DP is O(n). Recognizing linear complexity from the code should be automatic.
  • Word problems: the exam will not necessarily say "Fibonacci" — recognize the pattern behind the story. Rabbit problem: F(0) = 0, F(1) = 1, F(2) = 1, F(3) = 2, F(4) = 3, F(5) = 5, ..., F(12) = 144 pairs at the end of the year.
  • 0/1 knapsack: maximize the sum of p_i x_i with x_i in {0, 1} and total weight at most W; DP table with W+1 columns and n+1 rows; the B(k, w) recurrence; O(nw) time, which is pseudo-polynomial because of the w factor; if w is as large as 2^n, the DP is slower than brute force. Reconstructing the chosen objects: find where each profit value first appears.
  • Quiz: released this week (tonight), with five days to complete it; the portions cover everything up to today's session.
  • Syllabus: the in-semester syllabus is the complete syllabus — the complete handout. The extra topics covered beyond the live sessions are also examinable; do not skip them.
  • Mark split: the question paper is not set by a single person; a panel of faculty sets it, so the 25/75 split mentioned earlier is one possibility, not a hard rule.

Key Industry Applications

  • Communication networks: laying cables to connect all buildings within a campus; connecting telephone exchanges; leasing phone lines between cities at minimum total cost (the phone company charges different amounts for different city pairs) — an MST minimizes total cost.
  • Transportation networks: from a hub city (Bangalore), find the minimum-distance routes to several destinations (Hyderabad, Chennai, others) — an MST gives the cheapest connected structure.
  • Cluster analysis / K-means (K-clustering): find the MST of the data points, then delete the K−1 most expensive edges to get K clusters with small intra-cluster distance and large inter-cluster distance.
  • Image registration and segmentation: partition an image into significant regions; connect dots between homogeneous areas with a spanning tree so unrelated, disconnected parts fall outside it (for example, extracting a cat from a picture).
  • Taxonomy: the science of classification — related parts connected, unrelated parts disconnected.
  • Feature extraction in data mining and machine learning: the same MST view applies to features.
  • Dijkstra's algorithm (previous session): single source shortest path, the greedy-method sibling of Prim's algorithm.
  • Dynamic programming in practice: the same "solve each subproblem once and store it" pattern underlies shortest-path tables in navigation, sequence alignment in bioinformatics, and resource allocation in operations research.

DSA Lecture 11 notes · Minimum Spanning Trees and Dynamic Programming

Data Structures and Algorithms· postgraduate· 2026-08-09

Sections Breakdown

1Graphs — Recap

Recap of Dijkstra's algorithm and the formal definition of a graph as an ordered pair (V, E) of vertices and edges.

2Spanning Subgraphs and Spanning Trees

Spanning subgraphs keep every vertex but may drop edges; spanning trees are connected, cycle-free, and use exactly n-1 edges.

3Minimum Spanning Trees

Definition of the minimum spanning tree, the total weight formula, the pairwise-distinct uniqueness rule, and worked examples.

4Prim's Algorithm

The tree-growing greedy algorithm with two worked examples, the cycle rule, and O(E log V) analysis.

5Kruskal's Algorithm

The edge-sorting greedy algorithm with two worked examples, the cycle check, and O(E log E) analysis.

6Prim's vs Kruskal's — When to Use Which

Sparse versus dense graphs and the side-by-side comparison of the two MST algorithms.

7Applications of Minimum Spanning Trees

MSTs in communication and transportation networks, cluster analysis, image registration and segmentation, taxonomy, and feature extraction.

8Exam-Style Problem — Which Algorithm Produced This Partial Spanning Tree?

Deciding Prim's, Kruskal's, both, or neither for prematurely stopped runs, with worked analyses and practice guidance.

9Dynamic Programming — Foundations

Bellman's planning-based technique, overlapping subproblems, the contrast with divide and conquer, and the space-time trade-off.

10Fibonacci — The First Dynamic Programming Example

From the O(2^n) plain recursion to the O(n) iterative version, with the rabbit word problem and optimal substructure.

11The General Dynamic Programming Technique

The four conditions for dynamic programming: few-variable subproblems, subproblem optimality, overlap, and bottom-up construction.

12The 0/1 Knapsack Problem

The B(k, w) recurrence, the DP table, O(nw) pseudo-polynomial time, and reconstructing the chosen objects.

13Exam Guidance Summary

Distilled exam strategy: partial-tree questions, MST uniqueness, complexity rules, and word problems.

14Key Industry Applications

Real-world uses of minimum spanning trees and dynamic programming in industry.

Postgraduate students in Artificial Computational Intelligence

Exam Revision Notes

Below is the distilled, exam-ready core. Every entry comes from the full explanation above. Use this section for rapid review; return to the main notes when a point needs more context.

Graphs — Recap

Must-know: A graph is an ordered pair G = (V, E) with V a set of vertices and E a collection of edges; Dijkstra's algorithm solves single source shortest path under the greedy method.

⚠️ Top pitfall: Treating the rough definition (a collection of vertices and edges) as the whole story instead of understanding the ordered-pair idea.

Self-check: What two components make up a graph, and which one is a set?

Connects to: Spanning Subgraphs and Spanning Trees, Prim's Algorithm.

Spanning Subgraphs and Spanning Trees

Must-know: A spanning tree contains all vertices of the graph, is connected, has no cycles, and uses exactly n-1 edges for n vertices.

⚠️ Top pitfall: Reading "it will not be connected" as meaning a spanning tree can be disconnected — a tree is by definition connected and acyclic.

Self-check: How many edges does a spanning tree of a 6-vertex graph have?

Connects to: Graphs — Recap, Minimum Spanning Trees.

Minimum Spanning Trees

Must-know: An MST is the spanning tree of minimum total edge weight; uniqueness holds only when all edge weights are pairwise distinct.

⚠️ Top pitfall: Missing the phrase "pairwise distinct" — two equal weights somewhere in the graph can break the uniqueness of the MST.

Self-check: Can a graph have two MSTs with different total weights?

Connects to: Spanning Subgraphs and Spanning Trees, Prim's Algorithm, Kruskal's Algorithm.

Prim's Algorithm

Must-know: Prim's picks the shortest edge connected to any vertex already in the tree (not just the last vertex), never creates a cycle, stays a tree throughout, and runs in O(E log V) like Dijkstra.

⚠️ Top pitfall: Considering only the outgoing edges of the last visited vertex instead of all vertices already in the tree.

Self-check: Why is the edge G-I (weight 6) skipped in the nine-vertex example?

Connects to: Minimum Spanning Trees, Kruskal's Algorithm, Prim's vs Kruskal's — When to Use Which.

Kruskal's Algorithm

Must-know: Kruskal's starts from the minimum-weight edge, adds the next shortest edge that does not create a cycle, may be a forest during the process, and runs in O(E log E) = O(E log V).

⚠️ Top pitfall: Forgetting an equal-weight edge that creates no cycle (the G-F slip: the next edge was said to be A-B or C-F, but G-F was also weight 2).

Self-check: Why is the edge I-G (weight 6) skipped in the nine-vertex run?

Connects to: Minimum Spanning Trees, Prim's Algorithm, Prim's vs Kruskal's — When to Use Which.

Prim's vs Kruskal's — When to Use Which

Must-know: Use Kruskal for sparse graphs (edge based) and Prim for dense graphs (vertex based); both give the optimal MST.

⚠️ Top pitfall: Applying Prim's like BFS from only the last visited vertex instead of considering all vertices in the tree.

Self-check: Which algorithm is the better fit for a graph with very few edges?

Connects to: Prim's Algorithm, Kruskal's Algorithm.

Applications of Minimum Spanning Trees

Must-know: Clustering view: build the MST of data points, delete the K-1 most expensive edges to obtain K clusters.

Self-check: How do you get K clusters from a single MST of the data points?

Connects to: Minimum Spanning Trees.

Exam-Style Problem — Which Algorithm Produced This Partial Spanning Tree?

Must-know: For a prematurely stopped run: a disconnected partial tree means Kruskal's; to rule out Kruskal's you must trace its forced edge order (e.g. the 13-edge would be selected before any 14-edge); answers without explanation earn zero.

⚠️ Top pitfall: Missing the phrase "prematurely stopped" and treating the partial tree as a final MST.

Self-check: Why can a disconnected partial spanning tree only come from Kruskal's?

Connects to: Prim's Algorithm, Kruskal's Algorithm.

Dynamic Programming — Foundations

Must-know: Dynamic programming = dynamic planning (programming means planning); overlapping subproblems are solved once and stored; it is a space-for-time trade-off and an optimization of plain recursion.

⚠️ Top pitfall: Reading "programming" as computer programming instead of planning.

Self-check: What single difference separates dynamic programming from divide and conquer?

Connects to: Fibonacci — The First Dynamic Programming Example, The General Dynamic Programming Technique.

Fibonacci — The First Dynamic Programming Example

Must-know: Plain recursion is O(2^n); the iterative array version is O(n); recognize Fibonacci behind word problems like the rabbit story (F(12) = 144).

⚠️ Top pitfall: Expecting the exam to say "Fibonacci" literally — the pattern is hidden inside word problems.

Self-check: Why is F(2) = 1 in the rabbit problem?

Connects to: Dynamic Programming — Foundations, The 0/1 Knapsack Problem.

The General Dynamic Programming Technique

Must-know: The four requirements for DP: few-variable subproblems, subproblem optimality, overlapping subproblems, and bottom-up construction.

⚠️ Top pitfall: Assuming subproblem optimality always holds — the 0/1 knapsack shows it can fail for a naive subproblem definition.

Self-check: Name the four conditions under which dynamic programming applies.

Connects to: Dynamic Programming — Foundations, The 0/1 Knapsack Problem.

The 0/1 Knapsack Problem

Must-know: 0/1 knapsack: each item is entirely accepted or rejected; the DP table has W+1 columns and n+1 rows; B(k, w) copies the row above when w_k > w, else takes max(B(k-1, w), B(k-1, w-w_k) + p_k); O(nw) pseudo-polynomial time; reconstruction by first appearances.

⚠️ Top pitfall: Thinking the number of combinations is n factorial (it is 2^n), or believing the four-object optimum is part of the five-object optimum.

Self-check: Why does the DP look up B(k-1, w - w_k) instead of B(k-1, w) when the item fits?

Connects to: Dynamic Programming — Foundations, The General Dynamic Programming Technique.

Exam Guidance Summary

Must-know: Explanations earn the marks in the partial-tree question; pairwise distinct weights give a unique MST; the 0/1 knapsack runs in O(nw) pseudo-polynomial time.

⚠️ Top pitfall: Missing the word "prematurely stopped" and writing bare algorithm names without reasoning.

Self-check: What does the panel of faculty mean for the 25/75 mark split?

Connects to: Minimum Spanning Trees, Prim's Algorithm, Kruskal's Algorithm, Exam-Style Problem, Fibonacci, The 0/1 Knapsack Problem.

Key Industry Applications

Must-know: MSTs are the cheapest connected structure in networking and transportation; clustering = MST minus the K-1 most expensive edges.

Self-check: How does K-means relate to the minimum spanning tree?

Connects to: Minimum Spanning Trees, Applications of Minimum Spanning Trees.

Was this lecture useful?

Loading comments…
🤖

BitsNotes AI Assistant

Subject Notes Assistant

Configure AI Chat

Choose how to access the chatbot
Have your own API key?

Switch to "Bring Your Own Key" tab above for unlimited access with any OpenAI-compatible provider.

🔑 Enter API key above to fetch live models from provider, or enter model name manually.
OpenAI-Compatible API Support

Choose any provider preset (Gemini, DeepSeek, Kimi, GLM, MiniMax, Qwen, OpenAI, Groq, Ollama, etc.) or enter a custom endpoint URL.

Security & Privacy First

Your API key is sent directly from your browser to your specified provider. BitsNotes servers never store or see your key.