Problem (Parker Brothers, 1967). Four cubes have faces coloured with four colours. Stack them in a column so that each of the four long sides shows all four colours. There are ways to orient the cubes (41 472 up to rotating the whole column), but a graph turns it into a pencil-and-paper puzzle.

Graph method. Make a multigraph on the colours: for every cube draw its three opposite-face pairs as edges labelled by the cube (a pair of equal colours is a loop). A solution corresponds to two edge-disjoint subgraphs, each using exactly one edge of every cube and having every colour of degree exactly 2 (loops count 2): one for the front/back pair of each cube, one for left/right.

FactValue
orientations of one cube24 (6 choices of the front face 4 rotations)
graph choices per cube6 ordered pairs of opposite-face pairs
cubes, colourssame method; deciding solvability is NP-complete (Robertson and Munro, 1978)
if every colour appears exactly 6 times in totalthe third (unused) pairs also form a 2-regular subgraph, so solutions come in groups of 3 subgraphs

Example (faces listed as front, back, left, right, top, bottom; opposite pairs are positions 1-2, 3-4, 5-6):

CubeFacesOpposite pairsFront/back pairLeft/right pair
1R R G R R WRR, GR, RWGRRW
2W B B B G GWB, BB, GGWBGG
3W B G G R WWB, GG, RWWBRW
4W W B B G RWW, BB, GRGRBB

The front/back subgraph is the two 2-cycles G–R (cubes 1, 4) and W–B (cubes 2, 3); orienting them gives fronts G, W, B, R and backs R, B, W, G. The left/right subgraph is the 2-cycle R–W (cubes 1, 3) and the loops G (cube 2) and B (cube 4); lefts R, G, W, B and rights W, G, R, B. This is the only solution up to symmetry.

using Cube = array<int, 6>;                          // front, back, left, right, top, bottom: pairs (0,1), (2,3), (4,5)
 
// Graph method: returns for each cube the opposite pair used as front/back and the one used as left/right,
// or empty if the column cannot show all colours on every side. n cubes, colours 0..n-1.
vector<pair<int, int>> instantInsanity(const vector<Cube>& cubes) {
    int n = sz(cubes);
    auto regular = [&](const vector<int>& pick) {    // every colour has degree 2 in the chosen edges
        vector<int> deg(n, 0);
        for (int i = 0; i < n; i++) deg[cubes[i][2 * pick[i]]]++, deg[cubes[i][2 * pick[i] + 1]]++;
        return count(all(deg), 2) == n;
    };
    vector<vector<int>> factors; vector<int> pick(n);
    for (ll code = 0, tot = llround(pow(3, n)); code < tot; code++) {
        ll c = code; for (int i = 0; i < n; i++) pick[i] = c % 3, c /= 3;
        if (regular(pick)) factors.push_back(pick);
    }
    for (auto& f : factors) for (auto& g : factors) {
        bool disjoint = true; for (int i = 0; i < n; i++) disjoint &= f[i] != g[i];
        if (disjoint) { vector<pair<int, int>> res(n); for (int i = 0; i < n; i++) res[i] = {f[i], g[i]}; return res; }
    }
    return {};
}