Problem (Hamilton, 1857). On the 20 vertices and 30 edges of a dodecahedron (drawn flat as a board), find a tour along edges that visits every vertex exactly once and returns to the start: a Hamiltonian cycle. In Hamilton’s game the first player chooses the first five vertices and the second must complete the tour.

FactValue
dodecahedron graph20 vertices, cubic, planar, girth 5
Hamiltonian cycles30 (undirected)
Hamilton’s gameevery one of the 480 directed 5-vertex starting paths extends to a tour: 360 in exactly 2 ways, 120 in exactly 4 ways
Petersen graph (outer 5-cycle, inner pentagram, 5 spokes)Hamiltonian paths but no Hamiltonian cycle
Hamiltonian cycle in generalNP-complete, even for cubic planar graphs (Garey, Johnson and Tarjan, 1976)
exact algorithmbitmask DP , see Hamiltonian Paths and TSP

Board labels used below: outer pentagon , middle ring (a 10-cycle), inner pentagon ; outer joins middle , middle joins inner .

vector<vector<int>> dodecahedron() {
    vector<vector<int>> g(20);
    auto e = [&](int a, int b) { g[a].push_back(b); g[b].push_back(a); };
    for (int i = 0; i < 5; i++) { e(i, (i + 1) % 5); e(i, 5 + 2 * i); e(6 + 2 * i, 15 + i); e(15 + i, 15 + (i + 1) % 5); }
    for (int j = 0; j < 10; j++) e(5 + j, 5 + (j + 1) % 10);
    return g;
}
 
ll countHamiltonianCycles(const vector<vector<int>>& g) {   // undirected cycles, n <= 22; O(2^n n^2)
    int n = sz(g); vector<vector<ll>> dp(1 << n, vector<ll>(n, 0)); dp[1][0] = 1;   // paths from vertex 0
    for (int m = 1; m < (1 << n); m += 2) for (int v = 0; v < n; v++) if (dp[m][v])
        for (int u : g[v]) if (!(m >> u & 1)) dp[m | 1 << u][u] += dp[m][v];
    ll s = 0;
    for (int v = 1; v < n; v++) for (int u : g[v]) if (u == 0) s += dp[(1 << n) - 1][v];
    return n >= 3 ? s / 2 : 0;                       // each cycle is counted in both directions
}
 
vector<vector<int>> completeTours(const vector<vector<int>>& g, vector<int> path) {   // Hamilton's game
    int n = sz(g); vector<char> used(n, 0); for (int v : path) used[v] = 1;
    vector<vector<int>> res;
    auto go = [&](auto&& self) -> void {
        if (sz(path) == n) { for (int u : g[path.back()]) if (u == path[0]) res.push_back(path); return; }
        for (int u : g[path.back()]) if (!used[u]) { used[u] = 1; path.push_back(u); self(self); path.pop_back(); used[u] = 0; }
    };
    go(go);
    return res;
}