Hamiltonian Path
A delivery driver needs to visit every house in a neighborhood exactly once. Easy to describe — but finding the best route is one of the hardest problems in all of computer science.
A Hamiltonian path visits every vertex of a graph exactly once. A Hamiltonian circuit does the same and returns home. Unlike Eulerian paths (which visit every edge), there's no simple degree-check trick for Hamiltonian paths. You essentially have to try.
Why It's So Much Harder than Eulerian
Eulerian path: "visit every bridge once" → solvable in \(O(V+E)\) with a simple degree condition.
Hamiltonian path: "visit every house once" → NP-complete. No polynomial-time algorithm is known. No simple rule tells you whether one exists. The two problems sound almost the same, yet they're worlds apart in difficulty.
Brute Force: Try Every Route
The most obvious approach: try all possible orderings of the vertices. There are n! orderings — 10 vertices gives 3,628,800 routes to check. 20 vertices: 2.4 × 10^18. Completely infeasible beyond about 12 vertices.
Bitmask DP: The Held-Karp Trick
We can do much better with dynamic programming. The key observation: it doesn't matter how you visited a subset of vertices — only which subset you visited and where you are now matters for future decisions.
Define dp[mask][v] = true if there exists a valid path visiting exactly the vertices in mask and ending at vertex v. A bitmask encodes the subset compactly — bit i is 1 if vertex i has been visited.
Base case: dp[1 << v][v] = true for each starting vertex v.
Transition: dp[mask][v] = true if there exists a vertex u in mask (u ≠ v) such that dp[mask without v][u] = true and edge (u→v) exists.
Answer: a Hamiltonian path exists if dp[(1<<n)-1][v] is true for any v.
This runs in \(O(2^n · n^2)\) — still exponential, but the difference between \(O(n!)\) and \(O(2^n · n^2)\) is enormous. For n=20: 20! ≈ 2.4×10^18 vs 2^20 × 400 ≈ 4×10^8. The DP is about a billion times faster.
TSP: Add Edge Weights
The Travelling Salesman Problem extends Hamiltonian circuit with costs: find the minimum-cost circuit. Same DP works — store the minimum cost instead of a boolean. Same \(O(2^n · n^2)\) complexity, same NP-hardness.
For large n, approximation algorithms step in. For metric TSP (distances obey triangle inequality), the Christofides algorithm guarantees a solution at most 50% above optimal (3/2-approximation). A simple 2-approximation uses an MST: double all edges to create an Eulerian multigraph, find the circuit, then shortcut repeated vertices.