- No recipients within the immediate family
- Nobody should get who they got last year
- The whole thing should be a cycle (Sandy gives to George, George to Tom, Tom to Susan, Susan back to Sandy)
So at this point, I think what I’m looking at is a directed graph, and I want to find a random Eulerian Hamiltonian Cycle. Naively, I would say:
- Start with a random vertex
- Randomly choose a neighbour that hasn’t been hit yet
- Recurse until you reach a cycle (solution) or find a node with no neighbours (backtrack and choose a different random neighbour)
But this doesn’t give all permutations equal weight. Flipping a coin to choose the first neighbour could greatly limit subsequent possibilities, like in the graph below:
A -> [B, C] B -> [C, D, E] C -> [A, D, E] D -> [A, B, E] E -> [A, B]
If in the example above I start with A, I could choose B or C at 50% probability each.
- If I choose B, the only cycle is 1) A->B->C->D->E->A
- If I choose C, there are multiple paths: 2) A->C->D->B->E->A, 3) A->C->E->B->D->A
So with my naive approach, I would choose cycle 1 50% of the time, and 2 and 3 25% of the time each. The route I ended up taking this year was to shuffle all of the vertices, and then check if it was in fact an admissable cycle. But this gets less efficient as there are more constraints. Is there an efficient way to generate a random Hamiltonian Cycle where each cycle has equal probability?
Edit:
By “efficient” I mean more efficient in runtime and/or space than generating the set of every Hamiltonian Cycle, and then choosing one at random.
Asked By : Mark Peters
Answered By : Juho
S := {1,...,n} i := 1 X := {} while(not visited each permutation of S) if S is a valid solution set X to S with probability 1/i i := i + 1 S := next permutation of S
Best Answer from StackOverflow
Question Source : http://cs.stackexchange.com/questions/33839