Contents  |  ‹ Previous  |  Next ›  |  Download EPUB  |  PDF

Chapter 14
Graph Algorithms

1

14.1 Graph Theory

In the modern world, planning efficient routes is essential for business and industry, with applications as varied as product distribution, laying new fiber optic lines for broadband internet, and suggesting new friends within social network websites like Facebook.

This field of mathematics started nearly 300 years ago as a look into a mathematical puzzle (we’ll look at it in a bit). The field has exploded in importance in the last century, both because of the growing complexity of business in a global economy and because of the computational power that computers have provided us.

14.2 Graphs

14.2.1 Drawing Graphs

Example 14.1

Here is a portion of a housing development from Missoula, Montana2. As part of her job, the development’s lawn inspector has to walk down every street in the development making sure homeowners’ landscaping conforms to the community requirements.

Aerial photograph of a Missoula, Montana housing development showing several blocks of houses connected by a network of streets. The image motivates the question of whether a lawn inspector can walk every street without backtracking.

Figure 14.1: Aerial photograph of a Missoula, Montana housing development showing several blocks of houses...

Naturally, she wants to minimize the amount of walking she has to do. Is it possible for her to walk down every street in this development without having to do any backtracking? While you might be able to answer that question just by looking at the picture for a while, it would be ideal to be able to answer the question for any picture regardless of its complexity.

To do that, we first need to simplify the picture into a form that is easier to work with. We can do that by drawing a simple line for each street. Where streets intersect, we will place a dot.

Side-by-side: the housing aerial photo is overlaid with red dots at intersections and red lines along streets; next to it, the same network is redrawn as a graph of labeled vertices joined by edges, showing the reduction of a street map to a graph.

Figure 14.2: Side-by-side: the housing aerial photo is overlaid with red dots at intersections and red lines...

This type of simplified picture is called a graph.

Definition 14.2: Graphs, Vertices, and Edges

A graph consists of a set of dots, called vertices, and a set of edges connecting pairs of vertices.

While we drew our original graph to correspond with the picture we had, there is nothing particularly important about the layout when we analyze a graph. Both of the graphs below are equivalent to the one drawn above since they show the same edge connections between the same vertices as the original graph.

Eighteen-vertex housing-development graph with nodes A through R laid out on a roughly grid-like map of streets; reused from earlier in the chapter to ask whether an Euler circuit exists for the lawn inspector.

Figure 14.3: Eighteen-vertex housing-development graph with nodes A through R laid out on a roughly grid-like...
The same 18-vertex graph G (vertices A through R) redrawn with vertices scattered in a non-grid layout. The edge set is identical to the previous figure, illustrating that a graph's structure is independent of how it is drawn.
Figure 14.4: The same 18-vertex graph G (vertices A through R) redrawn with vertices scattered in a non-grid layout.

You probably already noticed that we are using the term graph differently than you may have used the term in the past to describe the graph of a mathematical function.

Example 14.3

Back in the 18th century in the Prussian city of Königsberg, a river ran through the city and seven bridges crossed the forks of the river. The river and the bridges are highlighted in the picture to the right

Historical map of the Prussian city of Koenigsberg with the river highlighted in blue and the seven bridges that cross its forks marked in green, depicting the geographic setting of the famous Koenigsberg bridge problem that launched graph theory.

Figure 14.5: Historical map of the Prussian city of Koenigsberg with the river highlighted in blue and the seven...
Image credit: Bogdan Giusca, Public Domain, CC-BY-SA 3.0.

As a weekend amusement, townsfolk would see if they could find a route that would take them across every bridge once and return them to where they started.

Leonard Euler (pronounced OY-lur), one of the most prolific mathematicians ever, looked at this problem in 1735, laying the foundation for graph theory as a field in mathematics. To analyze this problem, Euler introduced edges representing the bridges:

Schematic of Konigsberg's four landmasses drawn as labelled ellipses (North Bank, Island, East Bank, South Bank) with seven short line segments crossing between them representing the seven bridges of the puzzle.

Figure 14.6: Schematic of Konigsberg’s four landmasses drawn as labelled ellipses (North Bank, Island, East...

Since the size of each land mass it is not relevant to the question of bridge crossings, each can be shrunk down to a vertex representing the location:

Graph abstraction of the Konigsberg bridges: four circular vertices labelled NB, I, EB, and SB with seven edges connecting them, including two parallel arcs between NB and I and two between I and SB to represent the duplicate bridges (a multigraph).

Figure 14.7: Graph abstraction of the Konigsberg bridges: four circular vertices labelled NB, I, EB, and SB with...

Notice that in this graph there are two edges connecting the north bank and island, corresponding to the two bridges in the original drawing. Depending upon the interpretation of edges and vertices appropriate to a scenario, it is entirely possible and reasonable to have more than one edge connecting two vertices.

While we haven’t answered the actual question yet of whether or not there is a route which crosses every bridge once and returns to the starting location, the graph provides the foundation for exploring this question.

14.3 Definitions

While we loosely defined some terminology earlier, we now will try to be more specific.

Definition 14.4: Vertex

A vertex is a dot in the graph that could represent an intersection of streets, a land mass, or a general location, like “work” or “school”. Vertices are often connected by edges. Note that vertices only occur when a dot is explicitly placed, not whenever two edges cross. Imagine a freeway overpass – the freeway and side street cross, but it is not possible to change from the side street to the freeway at that point, so there is no intersection and no vertex would be placed.

Definition 14.5: Edges

Edges connect pairs of vertices. An edge can represent a physical connection between locations, like a street, or simply that a route connecting the two locations exists, like an airline flight.

Definition 14.6: Loop

A loop is a special type of edge that connects a vertex to itself. Loops are not used much in street network graphs.

Small graph illustrating a loop: three filled-dot vertices form a triangle and a red self-loop attaches to the rightmost vertex, showing an edge that connects a vertex to itself.

Figure 14.8: Small graph illustrating a loop: three filled-dot vertices form a triangle and a red self-loop...

Definition 14.7: Degree of a vertex

The degree of a vertex is the number of edges meeting at that vertex. It is possible for a vertex to have a degree of zero or larger.






Degree 0 Degree 1 Degree 2 Degree 3 Degree 4





Single isolated vertex with no edges, illustrating a vertex of degree 0 in the table of degree examples. A vertex with one edge attached, illustrating degree 1 in the table of degree examples. A vertex with two edges attached (forming a V), illustrating degree 2 in the table of degree examples. A vertex with three edges attached, illustrating degree 3 in the table of degree examples. A vertex with four edges attached (one to each diagonal direction), illustrating degree 4 in the table of degree examples.





Figure 14.9: Examples of vertices of degree 0 through 4.

Definition 14.8: Path

A path is a sequence of vertices using the edges. Usually we are interested in a path between two vertices. For example, a path from vertex A to vertex M is shown below. It is one of many possible paths in this graph.

A 3-by-4 grid graph with 12 vertices labelled A-D (top), E-H (middle), J-M (bottom). All grid edges are drawn; a path from A to M is highlighted in thick red, traversing A-E-F-G-L-M.

Figure 14.10: A 3-by-4 grid graph with 12 vertices labelled A-D (top), E-H (middle), J-M (bottom).

Definition 14.9: Circuit (a.k.a. cycle)

A circuit (a.k.a. cycle) is a path that begins and ends at the same vertex. A circuit (a.k.a. cycle) starting and ending at vertex A is shown below.

The same 3-by-4 grid graph (vertices A-D, E-H, J-M) with a circuit highlighted in thick red, beginning and ending at vertex A by traversing A-E-J-K-F-B-A and similar back path, illustrating a cycle.

Figure 14.11: The same 3-by-4 grid graph (vertices A-D, E-H, J-M) with a circuit highlighted in thick red...

Definition 14.10: Connected

A graph is connected if there is a path from any vertex to any other vertex. Every graph drawn so far has been connected. The graph below is disconnected; there is no way to get from the vertices on the left to the vertices on the right.

A 3-by-4 grid graph with vertices A-D, E-H, J-M, but with the column-A horizontal edges deleted so that vertex A and the left column are isolated from the rest, illustrating a disconnected graph.

Figure 14.12: A 3-by-4 grid graph with vertices A-D, E-H, J-M, but with the column-A horizontal edges deleted so...

Definition 14.11: Weights

Depending upon the problem being solved, sometimes weights are assigned to the edges. The weights could represent the distance between two locations, the travel time, or the travel cost. It is important to note that the distance between vertices in a graph does not necessarily correspond to the weight of an edge.

Learning Checkpoint 14.3.1

The graph below shows 5 cities. The weights on the edges represent the airfare for a one-way flight between the cities.

a.
How many vertices and edges does the graph have?
b.
Is the graph connected?
c.
What is the degree of the vertex representing LA?
d.
If you fly from Seattle to Dallas to Atlanta, is that a path or a circuit?
e.
If you fly from LA to Chicago to Dallas to LA, is that a path or a circuit?

Weighted graph of five U.S. cities (LA, Seattle, Chicago, Atlanta, Dallas) shown as filled dots arranged across the plane, with all ten edges drawn and labelled with one-way airfares such as $70 (LA-Seattle), $150 (LA-Dallas), $85 (Atlanta-Dallas), $75 (Chicago-Atlanta).

Figure 14.13: Weighted graph of five U.S. cities (LA, Seattle, Chicago, Atlanta, Dallas) shown as filled dots...

14.4 Shortest Path

Learning Outcomes

Resources

When you visit a website like Google Maps or use your Smartphone to ask for directions from home to your Aunt’s house in Pasadena, you are usually looking for a shortest path between the two locations. These computer applications use representations of the street maps as graphs, with estimated driving times as edge weights.

While often it is possible to find a shortest path on a small graph by guess-and-check, our goal in this chapter is to develop methods to solve complex problems in a systematic way by following algorithms. An algorithm is a step-by-step procedure for solving a problem. Dijkstra’s (pronounced dike-stra) algorithm will find the shortest path between two vertices.

Dijkstra’s Algorithm Dijkstra’s Algorithm
     

1.
Mark the ending vertex with a distance of zero. Designate this vertex as current.

Initial-state diagram for Dijkstra's algorithm: seven blue circular nodes T, E, A, NB, MR, P, Y connected by weighted edges (e.g., T-A=20, A-NB=36, NB-Y=120, MR-Y=90); each node has a green-boxed tentative-distance label, all set to infinity except the destination T which is 0.

Algorithm: Initial-state diagram for Dijkstra’s algorithm: seven blue circular nodes T, E, A, NB, MR, P, Y...

2.
Find all vertices leading to the current vertex. Calculate their distances to the end. Since we already know the distance the current vertex is from the end, this will just require adding the most recent edge. Don’t record this distance if it is longer than a previously recorded distance.
3.
Mark the current vertex as visited. We will never look at this vertex again.
4.
Mark the vertex with the smallest distance as current, and repeat from step 2.

Example 14.12

Suppose you need to travel from Yakima, WA (vertex Y) to Tacoma, WA (vertex T). Looking at a map, it looks like driving through Auburn (A) then Mount Rainier (MR) might be shortest, but it’s not totally clear since that road is probably slower than taking the major highway through North Bend (NB). A graph with travel times in minutes is shown below. An alternate route through Eatonville (E) and Packwood (P) is also shown.

Weighted road network for the Yakima-to-Tacoma example: seven filled-dot vertices T (Tacoma), E (Eatonville), A (Auburn), NB (North Bend), MR (Mount Rainier), P (Packwood), Y (Yakima) with edges labelled by travel times in minutes (e.g., T-A=20, A-NB=36, NB-Y=104, MR-Y=96, P-Y=76).

Figure 14.14: Weighted road network for the Yakima-to-Tacoma example: seven filled-dot vertices T (Tacoma), E...
Step 1: Mark the ending vertex with a distance of zero. The distances will be recorded in [brackets] after the vertex name.
Yakima-to-Tacoma road network as before, now with the destination Y annotated [0] in red to mark it as the starting vertex of Dijkstra's algorithm with tentative distance zero.
Figure 14.15: Yakima-to-Tacoma road network as before, now with the destination Y annotated [0] in red to mark it...
Step 2: For each vertex leading to Y, we calculate the distance to the end. For example, NB is a distance of 104 from the end, and MR is 96 from the end. Remember that distances in this case refer to the travel time in minutes.
Yakima example after Dijkstra step 2: tentative distances [104] at NB, [96] at MR, [76] at P are recorded in red next to each neighbour of Y; Y still labelled [0]; remaining vertices T, E, A are unlabelled.
Figure 14.16: Yakima example after Dijkstra step 2: tentative distances [104] at NB, [96] at MR, [76] at P are...
Step 3 & 4: We mark Y as visited, and mark the vertex with the smallest recorded distance as current. At this point, P will be designated current. Back to step 2.

Step 2 (#2): For each vertex leading to P (and not leading to a visited vertex) we find the distance from the end. Since E is 96 minutes from P, and we’ve already calculated P is 76 minutes from Y, we can compute that E is 96 + 76 = 172 minutes from Y.

If we make the same computation for MR, we’d calculate 76 + 27 = 103. Since this is larger than the previously recorded distance from Y to MR, we will not replace it.
Yakima example after the second iteration: P is the current vertex; E now has tentative distance [172] (via P), and Y is shown struck-through (visited); other labels [104] at NB, [96] at MR, [76] at P remain.

Figure 14.17: Yakima example after the second iteration: P is the current vertex; E now has tentative distance...
Step 3 & 4 (#2): We mark P as visited, and designate the vertex with the smallest recorded distance as current: MR. Back to step 2.

Step 2 (#3): For each vertex leading to MR (and not leading to a visited vertex) we find the distance to the end. The only vertex to be considered is A, since we’ve already visited Y and P. Adding MR’s distance 96 to the length from A to MR gives the distance 96 + 79 = 175 minutes from A to Y.
Yakima example after the third iteration: A has tentative distance [175] (via MR); P and Y appear struck-through (visited); NB still [104], MR [96], E [172].

Figure 14.18: Yakima example after the third iteration: A has tentative distance [175] (via MR); P and Y appear...
Step 3 & 4 (#3): We mark MR as visited, and designate the vertex with smallest recorded distance as current: NB. Back to step 2.

Step 2 (#4): For each vertex leading to NB, we find the distance to the end. We know the shortest distance from NB to Y is 104 and the distance from A to NB is 36, so the distance from A to Y through NB is 104 + 36 = 140. Since this distance is shorter than the previously calculated distance from Y to A through MR, we replace it.
Yakima example after the fourth iteration: A's distance is updated to [140] via NB; NB, MR, P, Y all struck-through; E still [172].

Figure 14.19: Yakima example after the fourth iteration: A’s distance is updated to [140] via NB; NB, MR, P, Y...
Step 3 & 4 (#4): We mark NB as visited, and designate A as current, since it now has the shortest distance.

Step 2 (#5): T is the only non-visited vertex leading to A, so we calculate the distance from T to Y through A: 20 + 140 = 160 minutes.
Yakima example after the fifth iteration: T receives tentative distance [160] via A; A, NB, MR, P, Y are struck-through, leaving E [172] still active. The shortest path Y-NB-A-T of 160 minutes is now determined.

Figure 14.20: Yakima example after the fifth iteration: T receives tentative distance [160] via A; A, NB, MR, P...
Step 3 & 4 (#5): We mark A as visited, and designate E as current.

Step 2 (#6): The only non-visited vertex leading to E is T. Calculating the distance from T to Y through E, we compute 172 + 57 = 229 minutes. Since this is longer than the existing marked time, we do not replace it.

Step 3 (#6): We mark E as visited. Since all vertices have been visited, we are done.

From this, we know that the shortest path from Yakima to Tacoma will take 160 minutes. Tracking which sequence of edges yielded 160 minutes, we see the shortest path is Y-NB-A-T.

Dijkstra’s algorithm is an optimal algorithm, meaning that it always produces the actual shortest path, not just a path that is pretty short, provided one exists. This algorithm is also efficient, meaning that it can be implemented in a reasonable amount of time. Dijkstra’s algorithm takes around V 2 calculations, where V is the number of vertices in a graph3. A graph with 100 vertices would take around 10,000 calculations. While that would be a lot to do by hand, it is not a lot for a computer to handle. It is because of this efficiency that your car’s GPS unit can compute driving directions in only a few seconds.

In contrast, an inefficient algorithm might try to list all possible paths then compute the length of each path. Trying to list all possible paths could easily take 10 25 calculations to compute the shortest path with only 25 vertices; that’s a 1 with 25 zeros after it! To put that in perspective, the fastest computer in the world would still spend over 1000 years analyzing all those paths.

Example 14.13: Dijkstra’s algorithm example

We would like to find a shortest path in the graph from node a to node g. See Code for python code to solve this problem and create these graphics.

Weighted undirected graph for the Dijkstra example. Seven vertices a-g are joined by edges with weights a-b=2, a-c=6, c-d=8, b-d=5, d-e=10, d-f=15, e-f=6, e-g=2, f-g=6. No vertex is yet marked visited.

Figure 14.21: Weighted undirected graph for the Dijkstra example.

We will initialize our algorithm at node ’a’.

Dijkstra step 1: the start vertex a is highlighted in red and labeled with tentative distance 0. Its neighbors b and c receive tentative labels 2 and 6 from a; all other vertices remain labeled infinity.

Figure 14.22: Dijkstra step 1: the start vertex a is highlighted in red and labeled with tentative distance 0.








current a b c d e f g








a 0 2 6









Dijkstra step 2: vertex b is now marked as visited with permanent distance 2, and the edge a-b is highlighted in red. Vertex d is updated through b to tentative distance 7. Labels at c, e, f, and g are unchanged.
Figure 14.23: Dijkstra step 2: vertex b is now marked as visited with permanent distance 2, and the edge a-b is...








current a b c d e f g








b 0 2 6 7









Dijkstra step 3: vertex c is marked visited with distance 6 and edge a-c is highlighted. Reaching d through c would give 6+8=14, which is worse than the current label 7, so d's tentative distance is unchanged.
Figure 14.24: Dijkstra step 3: vertex c is marked visited with distance 6 and edge a-c is highlighted.








current a b c d e f g








c 0 2 6 7









Dijkstra step 4: vertex d is marked visited with distance 7, and the path a-b-d is highlighted in red. Neighbors of d are updated: e to 17 (via 7+10) and f to 22 (via 7+15); g remains infinity.
Figure 14.25: Dijkstra step 4: vertex d is marked visited with distance 7, and the path a-b-d is highlighted in red.








current a b c d e f g








d 0 2 6 7 17 22









Dijkstra step 5: vertex e is marked visited with distance 17 and the edge d-e is added to the highlighted path. From e, vertex g is updated to 17+2=19, improving on its previous infinity label.
Figure 14.26: Dijkstra step 5: vertex e is marked visited with distance 17 and the edge d-e is added to the...








current a b c d e f g








e 0 2 6 7 17 22 19









Dijkstra step 6: vertex g is marked visited with distance 19, and the edge e-g is highlighted, completing a tentative shortest path a-b-d-e-g. The remaining unvisited vertex f keeps tentative distance 22.
Figure 14.27: Dijkstra step 6: vertex g is marked visited with distance 19, and the edge e-g is highlighted...








current a b c d e f g








g 0 2 6 7 17 22 19









Dijkstra step 7: vertex f is marked visited with distance 22 and the edge d-f is highlighted along with the previously found path. All seven vertices are now visited so the algorithm terminates.
Figure 14.28: Dijkstra step 7: vertex f is marked visited with distance 22 and the edge d-f is highlighted along...








current a b c d e f g








f 0 2 6 7 17 22 19









We can now summarize our calculations that followed Dijkstra’s algorithm.

Final state of the Dijkstra example: every vertex carries its shortest-path distance from a (a=0, b=2, c=6, d=7, e=17, g=19, f=22), and the shortest-path tree found by the algorithm is highlighted in red.

Figure 14.29: Final state of the Dijkstra example: every vertex carries its shortest-path distance from a (a=0...








current a b c d e f g








a 0 2 6








b 0 2 6 7








c 0 2 6 7








d 0 2 6 7 17 22








e 0 2 6 7 17 22 19








g 0 2 6 7 17 22 19








f 0 2 6 7 17 22 19









Final solution The shortest path from a to g is the path a - b - d - e - g,

The same seven-vertex weighted graph with the shortest path from a to g highlighted in red: a-b-d-e-g, traversing edges of weight 2, 5, 10, and 2 for a total length of 19.

Figure 14.30: The same seven-vertex weighted graph with the shortest path from a to g highlighted in red...

and has length

2 + 5 + 10 + 2 = 19.

Example 14.14

A shipping company needs to route a package from Washington, D.C. to San Diego, CA. To minimize costs, the package will first be sent to their processing center in Baltimore, MD then sent as part of mass shipments between their various processing centers, ending up in their processing center in Bakersfield, CA. From there it will be delivered in a small truck to San Diego.

The travel times, in hours, between their processing centers are shown in the table below. Three hours has been added to each travel time for processing. Find the shortest path from Baltimore to Bakersfield.








Baltimore Denver Dallas Chicago Atlanta Bakersfield







Baltimore * 15 14







Denver * 18 24 19







Dallas * 18 15 25







Chicago 15 18 18 * 14







Atlanta 14 24 15 14 *







Bakersfield 19 25 *







Table 14.1: Travel times in hours between processing centers, with three hours added for processing.

While we could draw a graph, we can also work directly from the table.

Step 1: The ending vertex, Bakersfield, is marked as current.

Step 2: All cities connected to Bakersfield, in this case Denver and Dallas, have their distances calculated; we’ll mark those distances in the column headers.

Step 3 & 4: Mark Bakersfield as visited. Here, we are doing it by shading the corresponding row and column of the table. We mark Denver as current, shown in bold, since it is the vertex with the shortest distance.








Baltimore Denver Dallas Chicago Atlanta Bakersfield
[19] [25]







Baltimore * 15 14







Denver * 18 24 19







Dallas * 18 15 25







Chicago 15 18 18 * 14







Atlanta 14 24 15 14 *







Bakersfield 19 25 *







Step 2 (#2): For cities connected to Denver, calculate distance to the end. For example, Chicago is 18 hours from Denver, and Denver is 19 hours from the end, the distance for Chicago to the end is 18 + 19 = 37 (Chicago to Denver to Bakersfield). Atlanta is 24 hours from Denver, so the distance to the end is 24 + 19 = 43 (Atlanta to Denver to Bakersfield).

Step 3 & 4 (#2): We mark Denver as visited and mark Dallas as current.








Baltimore Denver Dallas Chicago Atlanta Bakersfield
[25] [37] [43]







Baltimore * 15 14







Denver * 18 24 19







Dallas * 18 15 25







Chicago 15 18 18 * 14







Atlanta 14 24 15 14 *







Bakersfield 19 25 *







Step 2 (#3): For cities connected to Dallas, calculate the distance to the end. For Chicago, the distance from Chicago to Dallas is 18 and from Dallas to the end is 25, so the distance from Chicago to the end through Dallas would be 18 + 25 = 43. Since this is longer than the currently marked distance for Chicago, we do not replace it. For Atlanta, we calculate 15 + 25 = 40. Since this is shorter than the currently marked distance for Atlanta, we replace the existing distance.

Step 3 & 4 (#3): We mark Dallas as visited, and mark Chicago as current.








Baltimore Denver Dallas Chicago Atlanta Bakersfield
[37] [40]







Baltimore * 15 14







Denver * 18 24 19







Dallas * 18 15 25







Chicago 15 18 18 * 14







Atlanta 14 24 15 14 *







Bakersfield 19 25 *







Step 2 (#4): Baltimore and Atlanta are the only non-visited cities connected to Chicago. For Baltimore, we calculate 15+37 = 52 and mark that distance. For Atlanta, we calculate 14 + 37 = 51. Since this is longer than the existing distance of 40 for Atlanta, we do not replace that distance.

Step 3 & 4 (#4): Mark Chicago as visited and Atlanta as current.








Baltimore Denver Dallas Chicago Atlanta Bakersfield
[52] [40]







Baltimore * 15 14







Denver * 18 24 19







Dallas * 18 15 25







Chicago 15 18 18 * 14







Atlanta 14 24 15 14 *







Bakersfield 19 25 *







Step 2 (#5): The distance from Atlanta to Baltimore is 14. Adding that to the distance already calculated for Atlanta gives a total distance of 14 + 40 = 54 hours from Baltimore to Bakersfield through Atlanta. Since this is larger than the currently calculated distance, we do not replace the distance for Baltimore.

Step 3 & 4 (#5): We mark Atlanta as visited. All cities have been visited and we are done.

The shortest route from Baltimore to Bakersfield will take 52 hours, and will route through Chicago and Denver.

14.4.1 Run time improvements

Instance Generation. For each problem size n, we generate a random directed graph G = (V,E) with V = {0,1,,n 1} using an Erdős–Rényi model for digraphs. For every ordered pair (i,j) with ij, the arc (i,j) is included independently with probability p and assigned an integer weight wij sampled uniformly from a fixed range [w̲,w¯]. The source and sink are fixed as s = 0 and t = n 1. We measure wall-clock solve time for three approaches: NetworkX’s Dijkstra implementation, a binary MILP formulation solved via PuLP’s default solver, and the same MILP solved with Gurobi. To reduce variance, each size is replicated across several independently drawn graphs and the reported time is the mean over replications. To summarize performance trends, we fit simple runtime laws T(n) by least squares and report the best (highest R2) among (i) power law T(n) cnα, (ii) exponential T(n) ceβn, and (iii) quadratic T(n) an2 + bn + c.

Solver and Library Versions. The experiments were run with NetworkX version 2.5, PuLP version 2.4, and Gurobi runtime version (10, 0, 3). The default PuLP solver was CBC.

14.5 Spanning Trees

Learning Outcomes

Resources

A company requires reliable internet and phone connectivity between their five offices (named A, B, C, D, and E for simplicity) in New York, so they decide to lease dedicated lines from the phone company. The phone company will charge for each link made. The costs, in thousands of dollars per year, are shown in the graph.

A 4-vertex spanning tree drawn as filled dots at corners of a small region, connected by three edges forming a Y-shape (top-left to top vertex, bottom-right to middle, top to bottom-right), illustrating one possible spanning tree on four vertices.

Figure 14.31: A 4-vertex spanning tree drawn as filled dots at corners of a small region, connected by three...

In this case, we don’t need to find a circuit, or even a specific path; all we need to do is make sure we can make a call from any office to any other. In other words, we need to be sure there is a path from any vertex to any other vertex.

Definition 14.15: Spanning Tree

A spanning tree is a connected graph using all vertices in which there are no circuits. In other words, there is a path from any vertex to any other vertex, but no circuits.

Some examples of spanning trees are shown below. Notice there are no circuits in the trees, and it is fine to have vertices with degree higher than two.

A 4-vertex spanning tree with three edges arranged as a path: middle vertex linked to top-right, top-right linked to bottom-right, and bottom-right linked to bottom-left, showing another spanning-tree configuration on four vertices.

Figure 14.32: A 4-vertex spanning tree with three edges arranged as a path: middle vertex linked to top-right...
Composite figure of five small spanning trees with n = 1, 2, 3, 4, 5 vertices arranged left-to-right; each tree has exactly n-1 edges, demonstrating that a spanning tree on n vertices uses n-1 edges.
Figure 14.33: Composite figure of five small spanning trees with n = 1, 2, 3, 4, 5 vertices arranged...
n = 3 case from the spanning-tree examples: three labelled vertices A, B, C connected by two edges (A-B and B-C) forming a path, with exactly n-1 = 2 edges.
n = 4 case from the spanning-tree examples: a star tree with center B connected to leaves A, C, and D by three edges, illustrating n-1 = 3 edges on n = 4 vertices.
Five small spanning trees side by side on n = 1, 2, 3, 4, 5 vertices. Yellow circular nodes labelled A through E are connected by exactly n-1 edges in each, supporting the lemma that a tree on n vertices has n-1 edges.

Usually we have a starting graph to work from, like in the phone example above. In this case, we form our spanning tree by finding a subgraph – a new graph formed using all the vertices but only some of the edges from the original graph. No edges will be created where they didn’t already exist.

Question: How many edges are in a spanning tree of a connected graph?

Single yellow circular node labelled A drawn in isolation, illustrating the base case of the induction proof: a tree with one vertex and zero edges satisfies |E| = n - 1 = 0.

Figure 14.34: Examples of spanning trees with n = 1,2,3,4,5 nodes and exactly n 1 edges

Lemma 14.1. Number of Edges in a Spanning Tree Let G = (V,E) be a connected undirected graph with |V | = n. Then every spanning tree of G contains exactly n 1 edges.

Proof idea. We prove this by induction on the number of vertices n.

Base case ( n = 1): A tree with one vertex and no edges trivially satisfies the property |E| = 1 1 = 0.

A single yellow vertex labeled A with no edges: the smallest possible graph.

Figure 14.35: Base case: A single vertex with no edges

Inductive step: Assume that every tree with k vertices has exactly k 1 edges.

Now consider a tree with k + 1 vertices. Every tree has at least one leaf (a vertex of degree 1). Remove a leaf and its single incident edge. The resulting graph is still a tree (connected and acyclic) with k vertices.

By the inductive hypothesis, this smaller tree has k 1 edges. Adding back the removed leaf and its edge gives k edges total, which equals (k + 1) 1.

Pseudocode block titled 'Kruskal's Algorithm (Descriptive Version)'. Initialize T to empty; repeatedly pick the cheapest unused edge, skipping any edge that would create a cycle; stop once T contains |V|-1 edges, forming a minimum spanning tree of G.

Figure 14.36: Inductive step: Removing the leaf L and its dashed edge reduces the tree to 4 vertices and 3 edges

Thus, by induction, any tree with n vertices has exactly n 1 edges. □

Of course, any random spanning tree isn’t really what we want. We want the minimum cost spanning tree (MCST).

Definition 14.16: Minimum Cost Spanning Tree (MCST)

The minimum cost spanning tree is the spanning tree with the smallest total edge weight.

Applications of the Minimum Cost Spanning Tree (MCST):

1.
Network Design: When laying fiber optic cables, water pipes, or electrical wires to connect a set of cities or buildings, we want to ensure full connectivity at the lowest installation cost. An MCST gives the cheapest way to connect all locations without creating loops.
2.
Transportation Infrastructure: A transportation planner may need to connect a set of towns with roads while minimizing total construction cost. The MCST provides a plan to connect all towns with no redundant roads.
3.
Clustering in Machine Learning: In hierarchical clustering, data points can be viewed as nodes in a graph, with edges weighted by pairwise distances. The MCST captures the structure of the data, and removing the largest edges can reveal natural clusters.
4.
Reliable Communication Networks: For basic connectivity in communication systems (e.g., computer networks or telecommunications), an MCST ensures all devices are connected with minimal total wiring cost, providing a base network.
5.
Subroutines in Approximation Algorithms: The MCST is used as a key subroutine in approximation algorithms for NP-hard problems, such as the Traveling Salesperson Problem (TSP). For instance, the 2-approximation for metric TSP begins by constructing a minimum spanning tree to guide tour construction.

14.5.1 Kruskal’s Algorithm for Minimum Cost Spanning Tree

Kruskal’s algorithm is a surprisingly simple algorithm. It builds a spanning tree one edge at a time by choosing the cheapest next edge to add. But! It skips the edge if this edge would create a cycle.

Here is an algorithm description:

Algorithm: Kruskal’s Algorithm (Descriptive Version)

  Input: A connected, undirected graph G = (V,E) with edge weights w(e).

  Initialization: Mark all edges as unused. Set T .

repeat

  Select the cheapest unused edge in the graph.

if adding the edge would create a cycle then

  Skip this edge.

else

  Add the edge to T.

end if

until T contains |V | 1 edges (i.e., a spanning tree has been formed).

  Output: The set T, forming a minimum spanning tree of G.

In pseudocode, the algorithm looks like this:

Algorithm: Kruskal’s Algorithm

  Input: A connected, undirected graph G = (V,E) with weights w(e) on each edge e E.

  Initialization:

for each edge e E in sorted order do

if adding e to T does not form a cycle then

  Add e to T.

end if

if T contains |V | 1 edges then

  break

end if

end for

  Output: The set T, which forms a minimum spanning tree.

Example 14.17

Using our phone line graph from above, begin adding edges:

AB $4 OK
AE $5 OK
BE $6 reject – closes circuit ABEA
DC $7 OK
AC $8 OK
Five-vertex graph with cities A, B, C, D, E as black dots, fully connected with dollar-cost edge labels (AB=4, AE=5, AC=8, DC=7, plus higher cross-edges). Edges AB, AE, AC, DC are thick red, marking the MST built by Prim's algorithm starting at A.
Figure 14.37: Five-vertex graph with cities A, B, C, D, E as black dots, fully connected with dollar-cost edge...

At this point we stop – every vertex is now connected, so we have formed a spanning tree with cost $24 thousand a year.

Kruskal’s algorithm is both optimal and efficient; we are guaranteed to always produce the optimal MCST.

Example 14.18

The power company needs to lay updated distribution lines connecting the ten Oregon cities below to the power grid. How can they minimize the amount of new line to lay?












           
Ashland Astoria Bend Corvallis Crater Lake Eugene Newport Portland Salem Seaside











Ashland 374 200 223 108 178 252 285 240 356











Astoria 374 255 166 433 199 135 95 136 17











Bend 200 255 128 277 128 180 160 131 247











Corvallis 223 166 128 430 47 52 84 40 155











Crater Lake 108 433 277 430 453 478 344 389 423











Eugene 178 199 128 47 453 91 110 64 181











Newport 252 135 180 52 478 91 114 83 117











Portland 285 95 160 84 344 110 114 47 78











Salem 240 136 131 40 389 64 83 47 118











Seaside 356 17 247 155 423 181 117 78 118











Using Kruskal’s algorithm, we add edges from cheapest to most expensive, rejecting any that close a circuit. We stop when the graph is connected.

Seaside to Astoria 17 miles
Corvallis to Salem 40 miles
Portland to Salem 47 miles
Corvallis to Eugene 47 miles
Corvallis to Newport 52 miles
Salem to Eugene reject – closes circuit
Portland to Seaside 78 miles

The graph up to this point is shown to the right.

PIC
Figure 14.38: A spanning subgraph of the Oregon cities graph.

Continuing,

Newport to Salem reject
Corvallis to Portland reject
Eugene to Newport reject
Portland to Astoria reject
Ashland to Crater Lake 108 miles
Eugene to Portland reject
Newport to Portland reject
Newport to Seaside reject
Salem to Seaside reject
Bend to Eugene 128 miles
Bend to Salem reject
Astoria to Newport reject
Salem to Astoria reject
Corvallis to Seaside reject
Portland to Bend reject
Astoria to Corvallis reject
Eugene to Ashland 178 miles

This connects the graph. The total length of cable to lay would be 695 miles.

PIC
Figure 14.39: Another subgraph of the Oregon cities graph.

Exercise 14.19: Min Cost Spanning Tree

Find a minimum cost spanning tree on the graph below using Kruskal’s algorithm.

Undirected weighted graph with six yellow circular vertices A, B, C, E, F, G arranged hexagonally. Every pair is joined by an edge labelled with its integer weight (e.g. AB=11, BG=13, AE=14, EF=16, AC=33). Input graph for the Kruskal exercise.

Figure 14.40: Undirected weighted graph with six yellow circular vertices A, B, C, E, F, G arranged hexagonally.

Exercise 14.20: Networkx

Use the code below to load the prior exercise’s graph into Python. Then solve this problem using the Networkx package.

import networkx as nx 
 
# Create an undirected graph 
G = nx.Graph() 
 
# Add nodes (optional, as adding edges adds nodes implicitly) 
nodes = ['A', 'B', 'C', 'E', 'F', 'G'] 
G.add_nodes_from(nodes) 
 
# Add weighted edges 
edges = [ 
   ('A', 'B', 11), 
   ('A', 'C', 33), 
   ('A', 'E', 14), 
   ('A', 'F', 41), 
   ('A', 'G', 15), 
   ('B', 'C', 25), 
   ('B', 'E', 43), 
   ('B', 'F', 23), 
   ('B', 'G', 13), 
   ('C', 'E', 17), 
   ('C', 'F', 37), 
   ('C', 'G', 36), 
   ('E', 'F', 16), 
   ('E', 'G', 45), 
   ('F', 'G', 19) 
] 
 
G.add_weighted_edges_from(edges) 
 
# Optionally, visualize it 
# nx.draw(G, with_labels=True) 
# or use spring_layout or manual positions for a better view
Listing 14.1: Loading the graph into NetworkX

14.6 Exercise Answers

Exercise 14.3.1
(a)
5 vertices, 10 edges
(b)
Yes, it is connected.
(c)
The vertex is degree 4.
(d)
A path
(e)
A circuit
Exercise 14.23
The shortest path is ABDEG, with length 13.
Exercise 14.19
 
AB: Add, cost 11
BG: Add, cost 13
AE: Add, cost 14
AG: Skip, would create circuit ABGA
EF: Add, cost 16
EC: Add, cost 17

This completes the spanning tree.

Python code listing 'Loading the graph into NetworkX' that builds the prior 6-vertex weighted graph in NetworkX: it imports nx, creates an undirected Graph, adds nodes A,B,C,E,F,G, and feeds the 15 weighted edges via G.add_weighted_edges_from(edges).

14.6.1 Prim’s Algorithm for Minimum Cost Spanning Tree

Algorithm: Prim’s Algorithm (Descriptive Version)

  Input: A connected, undirected graph G = (V,E) with edge weights w(e).

  Initialization: Start with any vertex v V . Let T {v} and ET .

repeat

  Find the cheapest edge with one endpoint in T and one endpoint not in T.

  Add that edge to ET and its other endpoint to T.

until T includes all vertices.

  Output: The set ET, forming a minimum spanning tree of G.

In pseudocode, the algorithm looks like this:

Algorithm: Prim’s Algorithm

  Input: A connected, undirected graph G = (V,E) with weights w(e) on each edge.

  Initialization:

while |T| < |V | do

  Among all edges (u,v) E with u T and vT, find the one with minimum weight.

  Add v to T, and (u,v) to ET.

end while

  Output: The set ET, which forms a minimum spanning tree.

Example 14.21

Using our phone line graph from above, begin with vertex A and grow the tree:

Start at A
AB $4 add AB
AE $5 add AE
BE $6 reject – E already added
DC $7 add DC
AC $8 add AC
Five-vertex graph with cities A, B, C, D, E as black dots, fully connected with dollar-cost edge labels (AB=4, AE=5, AC=8, DC=7, plus higher cross-edges). Edges AB, AE, AC, DC are thick red, marking the MST built by Prim's algorithm starting at A.

The same minimum cost spanning tree is produced, and we stop once all vertices have been added to the tree.

Just like Kruskal’s algorithm, Prim’s algorithm is guaranteed to find the optimal minimum spanning tree. However, it grows the tree from a single root and adds the cheapest connecting edge at each step, which makes it especially efficient when implemented with a priority queue (e.g., using a Fibonacci heap for near-linear time in sparse graphs).

Exercise 14.22: Prim’s Algorithm

Use Prim’s algorithm to find a minimum cost spanning tree on the same graph as in Exercise 14.19, starting from vertex A. Show the steps as you add edges and vertices to the growing tree.

Same five-city phone-line graph (A, B, C, D, E) used to illustrate Prim's algorithm. Edges are labelled with dollar costs and the spanning tree edges AB, AE, AC, DC are drawn in thick red while the remaining inter-city edges are thin black.

Figure 14.41: Prim’s algorithm

14.7 Exercises

The exercises in this chapter are arranged in three bands that build on one another. Skills items drill the mechanics: translating maps and tables into graphs, computing degrees, and running Dijkstra’s and Kruskal’s algorithms by hand. Concepts items ask you to explain why the algorithms work and what their limits are. Explorations are longer, open-ended activities suited to group work. Within each band, items follow the order in which the material appears in the chapter.

Exercise 14.23: Shortest Path Problem

Find the shortest path between vertices A and G in the graph below.

Boxed figure for Prim's algorithm: 7-vertex graph with vertices a, b, c, d, e, f, g as red circles. The minimum spanning tree edges d-a, d-f, a-b, b-e, e-c, e-g are drawn thick red; remaining edges are thin black with integer weights.

Figure 14.42: Boxed figure for Prim’s algorithm: 7-vertex graph with vertices a, b, c, d, e, f, g as red circles.

Skills

1.
To deliver mail in a particular neighborhood, the postal carrier needs to walk along each of the streets with houses (the dots). Create a graph with edges showing where the carrier must walk to deliver the mail.

Exercise diagram: a stylized neighborhood shown as six rectangular blocks in two rows of three. Black squares on the inside borders of each block mark houses; students draw edges along the streets the carrier walks to reach every house.

Figure 14.43: Exercise diagram: a stylized neighborhood shown as six rectangular blocks in two rows of three.
2.
Suppose that a town has 7 bridges as pictured below. Create a graph that could be used to determine if there is a path that crosses all bridges once.

Exercise map of a fictional town: a teal river divides the area into several land masses, with seven black bars marking bridges. Students convert the map to a graph to test for an Eulerian path crossing each bridge once.

Figure 14.44: Exercise map of a fictional town: a teal river divides the area into several land masses, with...
3.
The table below shows approximate driving times (in minutes, without traffic) between five cities in the Dallas area. Create a weighted graph representing this data.
4.
Shown in the table below are the one-way airfares between 5 cities4. Create a graph showing this data.
5.
Find the degree of each vertex in the graph below.

Seven-vertex weighted graph for the shortest-path exercise. Vertices A, B, C, D, E, F, G in a roughly diamond layout with integer edge weights (AB=1, AC=4, BD=3, CD=2, DE=2, DF=4, EG=7, FG=6, plus chords). Goal: find the shortest path from A to G.

Figure 14.45: Seven-vertex weighted graph for the shortest-path exercise.
6.
Find the degree of each vertex in the graph below.

Airfare table giving one-way dollar fares between Seattle, Honolulu, London, Moscow, and Cairo (e.g. Seattle-Honolulu $159, Honolulu-London $830, London-Moscow $245, Moscow-Cairo $329). Used as input for building a weighted graph.

Figure 14.46: Airfare table giving one-way dollar fares between Seattle, Honolulu, London, Moscow, and Cairo (e.g.
7.
Which of these graphs are connected?



Small undirected graph with five black-dot vertices arranged in two rows, with four edges (square plus a diagonal extension). One of three example graphs presented side-by-side asking 'Which of these graphs are connected?'. Small undirected graph with five black-dot vertices; edges form one triangle on the right plus a separate vertical segment on the left, leaving the graph in two components. One of three connectivity examples. Small undirected graph with five black-dot vertices fully linked through a series of edges so all vertices belong to one component. The third option in the 'Which of these graphs are connected?' exercise.




Figure 14.47: Three five-vertex graphs for the connectedness exercise.
8.
Which of these graphs are connected?



Eight-vertex graph drawn on a 3-by-3 grid layout with three short horizontal segments stacked at top, middle, and bottom; the components are not all linked, illustrating a disconnected graph for the second connectivity question. Eight-vertex graph on a 3-by-3 grid layout where a central vertex (1.5,1) has high degree, connecting most of the graph; one corner pair remains separated. Used for the second 'Which of these graphs are connected?' question. Eight-vertex graph with edges forming a connected outer cycle plus several interior diagonals; the third option in the second connectivity exercise.




Figure 14.48: Three more graphs for the connectedness exercise.
9.
Travel times by rail for a segment of the Eurail system is shown below with travel times in hours and minutes. Find path with shortest travel time from Bern to Berlin by applying Dijkstra’s algorithm.

PIC

Figure 14.49: European rail network with travel times between cities.
10.
Using the graph from the previous problem, find the path with shortest travel time from Paris to München.
11.
Find a minimum cost spanning tree for the graph you created in problem #3.
12.
A company wants to connect its 5 buildings with fiber optic cable. Costs (in thousands of dollars) to lay cables between pairs of buildings are shown below. Find a minimum cost spanning tree connecting the buildings.

Weighted graph on five labelled vertices A, B, C, D, E in a pentagonal layout, fully connected by ten edges with dollar-cost labels (e.g. CD=$5.6, CA=$5.1, BC=$4.3, AE=$4.4, CE=$4.0); used to plan a minimum-cost sonet ring.

Figure 14.50: Weighted graph on five labelled vertices A, B, C, D, E in a pentagonal layout, fully connected by...
13.
Passenger rail travel times, in minutes, between five Virginia cities and Washington, D.C. are shown below. Apply Dijkstra’s algorithm, exactly as in the worked examples of §14.4 and in Exercise 9, to find the route with shortest travel time from Bristol to Washington. Record the distance labels as they become permanent.

PIC

Figure 14.51: Virginia cities road network with distances.
14.4, Exercise 9]
14.
Using Kruskal’s algorithm, find a minimum cost spanning tree for the airfare graph you created in problem #4. List the edges in the order the algorithm considers them, noting any edge that is rejected because it would close a circuit. What would an airline alliance use such a tree for?

14.5.1]

Concepts

15.
Can a graph have one vertex with odd degree? If not, are there other values that are not possible? Why?
16.
Kruskal’s algorithm is greedy: at every step it grabs the cheapest edge available, with no regard for what comes later. Explain informally why this shortsightedness never costs anything for spanning trees. Suppose the algorithm’s tree T skipped some edge e that belongs to a cheaper spanning tree; use the fact that adding e to T closes exactly one circuit to argue that the cheaper tree can be repaired, one edge at a time, into Kruskal’s tree without ever increasing the cost. Would the same reasoning work if some edge costs were negative?

14.5.1]

17.
Dijkstra’s algorithm permanently marks the unvisited vertex with the smallest recorded distance and never revisits it. Explain why this is justified when all edge weights are nonnegative. Then construct a graph with three vertices, one of which has a negative edge weight, on which the algorithm returns a wrong answer.

14.4]

Explorations

18.
Social networks such as Facebook and LinkedIn can be represented using graphs in which vertices represent people and edges are drawn between two vertices when those people are “friends.” The table below shows a friendship table, where an X shows that two people are friends.











A B C D E F G H I










A X X X X










B X X










C X










D X X










E X X










F X X










G X










H X










Table 14.4: Friendship table: an X marks pairs of people who are friends.

(a)
Create a graph of this friendship table
(b)
Find the shortest path from A to D. The length of this path is often called the “degrees of separation” of the two people.
(c)
Extension: Split into groups. Each group will pick 10 or more movies, and look up their major actors (www.imdb.com is a good source). Create a graph with each actor as a vertex, and edges connecting two actors in the same movie (note the movie name on the edge). Find interesting paths between actors, and quiz the other groups to see if they can guess the connections.
19.
A spell checker in a word processing program makes suggestions when it finds a word not in the dictionary. To determine what words to suggest, it tries to find similar words. One measure of word similarity is the Levenshtein distance, which measures the number of substitutions, additions, or deletions that are required to change one word into another. For example, the words spit and spot are a distance of 1 apart; changing spit to spot requires one substitution (i for o). Likewise, spit is distance 1 from pit since the change requires one deletion (the s). The word spite is also distance 1 from spit since it requires one addition (the e). The word soot is distance 2 from spit since two substitutions would be required.
(a)
Create a graph using words as vertices, and edges connecting words with a Levenshtein distance of 1. Use the misspelled word “moke” as the center, and try to find at least 10 connected dictionary words. How might a spell checker use this graph?
(b)
Improve the method from above by assigning a weight to each edge based on the likelihood of making the substitution, addition, or deletion. You can base the weights on any reasonable approach: proximity of keys on a keyboard, common language errors, etc. Use Dijkstra’s algorithm to find the length of the shortest path from each word to “moke”. How might a spell checker use these values?

Selected Solutions

Solution

(Exercise 9) Run Dijkstra’s algorithm from Bern. The vertices become permanently labeled in the order: Bern (0:00), Lyon (3:50), Frankfurt (3:55), Paris (5:45, via Lyon), München (7:05, via Frankfurt), Amsterdam (7:10, via Paris), Berlin (12:50, via München). The shortest route is

Bern Frankfurt München Berlin,3:55 + 3:10 + 5:45 = 12:50.

For comparison, Bern–Frankfurt–Amsterdam–Berlin takes 14:05 and Bern–Lyon–Paris–Amsterdam–Berlin takes 13:20.

Solution

(Exercise 12) Using Kruskal’s algorithm, the four cheapest edges are accepted one after another with no rejections: CE (4.0), BD (4.3), AE (4.4), AD (4.7). These four edges connect all five buildings, so the algorithm stops. The minimum cost spanning tree is {CE,BD,AE,AD} with total cost 4.0 + 4.3 + 4.4 + 4.7 = 17.4, i.e., $17,400. (A spanning tree is the cheapest way to connect the buildings, but it offers no backup path if a cable is cut.)

Solution

(Exercise 13) Running Dijkstra’s algorithm from Washington, the labels become permanent in the order: Washington (0), Richmond (115), Charlottesville (140), Lynchburg (210, via Charlottesville), Roanoke (260, via Charlottesville), Bristol (405). The shortest route is

Bristol Roanoke Charlottesville Washington,145+120+140 = 405 minutes,

that is, 6 hours 45 minutes. For comparison, routing through Lynchburg takes 145 + 55 + 70 + 140 = 410 minutes and routing through Richmond takes 145 + 55 + 125 + 115 = 440 minutes.

Solution

(Exercise 14) Sorting the airfares from cheapest to most expensive, Kruskal’s algorithm accepts Seattle–Honolulu ($159), London–Moscow ($245), and London–Cairo ($323); it then rejects Moscow–Cairo ($329) because that edge would close the circuit London–Moscow–Cairo, and finally accepts Seattle–London ($370), which connects all five cities. The minimum cost spanning tree has total cost 159 + 245 + 323 + 370 = $1097. Such a tree gives the cheapest set of routes that still links every city, though any trip between cities in different branches must connect through intermediate stops.

Solution

(Exercise 16) Suppose a spanning tree T uses an edge e that Kruskal’s tree T skipped. Kruskal’s algorithm rejected e only because, at the moment e was examined, e closed a circuit with edges already accepted; since edges are examined from cheapest to most expensive, every edge on that circuit costs no more than e. That circuit must contain some edge fT (a tree cannot contain a whole circuit). Replacing e by f in T yields another spanning tree that is no more expensive, and which agrees with T on one more edge. Repeating this exchange turns T into T without ever increasing the cost, so T is at least as cheap as any spanning tree. The argument never used the sign of the costs, only their order, so it works with negative edge costs too; note the contrast with Dijkstra’s algorithm, which does rely on nonnegative weights (Exercise 17).

14.7.1 Notes

Dijkstra’s algorithm was introduced by Edsger W. Dijkstra in his 1959 paper “A note on two problems in connexion with graphs,” Numerische Mathematik 1, 269–271. The algorithm finds the shortest path between two nodes; a common variant finds the shortest paths from a single source node to every other node in the network.

Notes, References, and Resources

Resources

Youtube! Video of many graph algorithms by Google engineer (6+ hours)

Graph Libraries in Python

Several graph libraries are available in Python, each with distinct strengths depending on your needs. NetworkX is widely used for its ease of use and flexibility, especially for small to medium-sized graphs. For high-performance analysis on large graphs, graph-tool and NetworKit offer optimized implementations of common graph algorithms. igraph strikes a balance between speed and usability, while libraries like PyTorch Geometric and DGL are specifically designed for machine learning on graphs. The table below compares key features across several popular graph libraries.

Library Speed Ease of Use Graph Size Algorithms Visualization
NetworkX Low High Small–Medium Basic Moderate
graph-tool Very High Low Large Advanced Basic
igraph High Moderate Medium–Large Strong Limited
NetworKit Very High Low Very Large Advanced None
PyTorch Geometric Very High Low Large ML-Specific None
Table 14.5: Comparison of Python Graph Libraries
© 2026 Robert Hildebrand and contributors · Licensed CC BY-SA 4.0 · Sources and attribution · Book home