Graphs and how computers store them
A graph has vertices (nodes) and edges (links). Edges may be directed (one-way arrows) and may have weights (distance, cost, time or capacity).
- Adjacency matrix: a table where row i, column j holds the weight of edge i→j (or 0). Fast to check one edge; uses n² space.
- Adjacency list: each vertex keeps a list of its neighbours. Saves space when the graph has few edges (sparse).
The degree of a vertex is the number of edges at it. In the 3D graph, C has degree 4.
Traversals: breadth-first and depth-first
Breadth-first search (BFS)
- Put the start vertex in a queue and mark it visited.
- Take the vertex at the front of the queue.
- Add each unvisited neighbour to the back of the queue and mark it.
- Repeat until the queue is empty.
BFS finds the path with the fewest edges in an unweighted graph. Uses: shortest route in a maze, friends of friends, web crawlers.
Depth-first search (DFS)
- Visit the start vertex and mark it.
- Go to an unvisited neighbour and repeat from there (push onto a stack, or use recursion).
- At a dead end, backtrack (pop) to the last vertex with an unvisited neighbour.
Uses: solving mazes and puzzles, finding cycles, checking whether a graph is connected, topological sort of tasks.
Both take time proportional to V + E (vertices + edges) with an adjacency list.
Tree traversals: pre-order, in-order, post-order
A tree is a connected graph with no cycles. For a binary tree, DFS can visit the root at three different moments:
- Pre-order: root, left, right – used to copy a tree or write prefix (Polish) notation.
- In-order: left, root, right – gives the values of a binary search tree in sorted order.
- Post-order: left, right, root – used to delete a tree or evaluate postfix (Reverse Polish) expressions.
Example: tree with root 8, left child 3 (children 1 and 6), right child 10. Pre-order: 8, 3, 1, 6, 10. In-order: 1, 3, 6, 8, 10. Post-order: 1, 6, 3, 10, 8.
Dijkstra's shortest-path algorithm
- Give the start vertex distance 0 and all others ∞.
- Pick the unfixed vertex with the smallest distance and fix it (its distance is now final).
- For each neighbour, if (fixed distance + edge weight) is smaller than its current distance, update it and note where it came from.
- Repeat until all vertices are fixed. Trace back the "came from" notes to get the route.
In the 3D graph from A: A = 0, C = 2, B = 3 (via C, not the direct road of 4), D = 8, E = 10, F = 13. Dijkstra only works when no weight is negative. With a priority queue it runs in about (V + E) log V time.
Minimum spanning trees, route inspection and the travelling salesperson
Minimum spanning tree (MST)
A spanning tree joins all V vertices with V − 1 edges and no cycles. The MST has the smallest total weight.
- Kruskal: sort edges by weight; add each edge unless it makes a cycle.
- Prim: start anywhere; repeatedly add the cheapest edge joining the tree to a new vertex (easy to do on a distance table).
In the 3D graph: BC 1, AC 2, DE 2, EF 3, BD 5 → total 13 km (AB 4 is rejected: it would make a cycle).
Route inspection (Chinese postman)
Find the shortest closed route that uses every edge at least once. If all degrees are even, the answer is the total weight. Otherwise pair up the odd-degree vertices and add the shortest paths between the pairs. In the 3D graph, B and E are odd; total weight 41 + shortest B–E path 7 = 48 km.
Travelling salesperson (TSP)
Find the shortest tour visiting every vertex once and returning. No fast exact method is known, so we find bounds:
- Upper bound: the nearest-neighbour tour (always go to the nearest unvisited vertex).
- Lower bound: delete one vertex, find the MST of the rest, then add the two shortest edges from the deleted vertex.
The best tour lies between the two bounds.
Network flows: max flow and min cut
A flow network is a directed graph where each arc has a capacity (most it can carry), like pipes or roads. Flow leaves a source S and reaches a sink T. At every other vertex, flow in = flow out.
- A cut splits the vertices into a part with S and a part with T. Its capacity is the sum of capacities of arcs going from the S side to the T side.
- Max-flow min-cut theorem: the largest possible flow equals the capacity of the smallest cut.
- Flow augmentation: start with any valid flow, find a path from S to T with spare capacity (it may push back along an arc already carrying flow), add flow along it, repeat until none is left.
- Several sources or sinks? Add a supersource joined to each source, and a supersink, with unlimited capacity.
- An arc may also have a lower capacity (it must carry at least that much). A flow is feasible only if every arc stays between its lower and upper capacity.
Example: S→A 4, S→B 3, A→B 2, A→T 3, B→T 4. Send 3 along S-A-T, 3 along S-B-T, 1 along S-A-B-T: flow 7. The cut {S} | {A, B, T} has capacity 4 + 3 = 7, so 7 is the maximum.
Try it: be the algorithm
Draw 6 dots for houses on your street and join them with lines; write distances in steps. Run Dijkstra by hand from your house using a table, then check with the free-play step (use start A). Then find the cheapest way to connect every house with cable (MST).
Key formulas and definitions
- BFS uses a queue (first in, first out); DFS uses a stack (last in, first out) or recursion
- Dijkstra update: if d(v) + w(v,u) < d(u) then d(u) = d(v) + w(v,u)
- A spanning tree on V vertices has V − 1 edges
- Route inspection = total weight + shortest paths pairing the odd vertices
- Max flow = capacity of the minimum cut
Worked examples
1. Run BFS from A on the 3D graph (neighbours in alphabetical order). Give the visit order.
Queue: A → take A, add B, C → take B, add D → take C, add E → take D, add F → take E → take F. Order: A, B, C, D, E, F. Layers: B, C at 1 edge; D, E at 2; F at 3.
2. Use Dijkstra from A to find the shortest route to F.
Fix A 0. Update B 4, C 2. Fix C 2; update B to 3 (via C), D 12, E 10. Fix B 3; D becomes 8. Fix D 8; E stays 10, F 14. Fix E 10; F becomes 13. Fix F 13. Route: A–C–B–D–E–F = 2 + 1 + 5 + 2 + 3 = 13 km.
3. Use Kruskal's algorithm to find the MST of the 3D graph.
Sorted: BC 1, AC 2, DE 2, EF 3, AB 4, BD 5, DF 6, CE 8, CD 10. Add BC, AC, DE, EF. AB makes cycle A-B-C: reject. Add BD. Now 5 edges for 6 vertices: done. Total = 1 + 2 + 2 + 3 + 5 = 13.
4. Give the pre-, in- and post-order traversals of the tree: root 8, left 3 (children 1 and 6), right 10.
Pre-order 8, 3, 1, 6, 10. In-order 1, 3, 6, 8, 10 (sorted, as it is a BST). Post-order 1, 6, 3, 10, 8.
5. Find the route inspection length for the 3D graph, starting and ending at A.
Degrees: A2, B3, C4, D4, E3, F2. Odd: B and E. Shortest B–E: B–D–E = 7 (B–C–E = 9). Total weight = 41. Route = 41 + 7 = 48 km; roads B–D and D–E are walked twice.
6. Network: S→A 4, S→B 3, A→B 2, A→T 3, B→T 4. Find the maximum flow and prove it.
Augment S-A-T by 3, S-B-T by 3, S-A-B-T by 1: flow = 7. Cut separating S from the rest has capacity 4 + 3 = 7. Flow = cut, so 7 is the maximum (max-flow min-cut).
Common mistakes
- Using a stack for BFS or a queue for DFS. BFS needs a queue; DFS needs a stack.
- Fixing a vertex in Dijkstra as soon as it gets a label. Only the smallest unfixed label is fixed each time.
- In Kruskal, adding an edge that forms a cycle just because it is cheap.
- Counting a cut's capacity using arcs that go from the T side back to the S side. Only S-side → T-side arcs count.