Todas las Navidades sacamos nombres para intercambios de regalos en mi familia. Esto generalmente involucra varios redibujados hasta que nadie haya retirado a su cónyuge. Así que este año codifiqué mi propia aplicación de dibujo que incluye un montón de nombres, un grupo de emparejamientos no permitidos, y envía un correo electrónico a todos con su regalo elegido.Algoritmo secreto de santa
En este momento, el algoritmo funciona así (en pseudocódigo):
function DrawNames(list allPeople, map disallowedPairs) returns map
// Make a list of potential candidates
foreach person in allPeople
person.potentialGiftees = People
person.potentialGiftees.Remove(person)
foreach pair in disallowedPairs
if pair.first = person
person.Remove(pair.second)
// Loop through everyone and draw names
while allPeople.count > 0
currentPerson = allPeople.findPersonWithLeastPotentialGiftees
giftee = pickRandomPersonFrom(currentPerson.potentialGiftees)
matches[currentPerson] = giftee
allPeople.Remove(currentPerson)
foreach person in allPeople
person.RemoveIfExists(giftee)
return matches
¿Hay alguien que sabe más sobre la teoría de grafos conocen algún tipo de algoritmo que funcionaría mejor aquí? Para mis propósitos, esto funciona, pero tengo curiosidad.
EDIT: Dado que los correos electrónicos se publicaron hace un tiempo, y estoy esperando aprender algo, lo expresaré de nuevo como una pregunta de teoría de grafos. No estoy tan interesado en los casos especiales en los que las exclusiones son todas parejas (como que los cónyuges no se conocen). Estoy más interesado en los casos en que hay suficientes exclusiones que encontrar una solución se convierte en la parte difícil. Mi algoritmo anterior es solo un algoritmo codicioso simple que no estoy seguro de que tenga éxito en todos los casos.
Comenzando con un gráfico dirigido completo y una lista de pares de vértices. Para cada par de vértices, elimine el borde del primer vértice al segundo.
El objetivo es obtener un gráfico en el que cada vértice tenga un borde hacia adentro y un borde hacia la izquierda.
¡Eso es lo que estaba buscando! ¡Gracias! – Eclipse
No del todo: es un gráfico dirigido, y no necesariamente quiere una correspondencia perfecta; solo desea un subgrafo de tal manera que cada vértice tenga indegree = outdegree = 1 - a * cubierta de ciclo *. [Hay formas de reducirlo a un problema de coincidencia perfecto, pero también hay formas de resolverlo directamente.] – ShreevatsaR
@ShreevatsaR: No es necesario que dirija el gráfico. Simplemente voltea una moneda para elegir una dirección para cada ciclo. (Esto supone que todos los pares de la lista negra son simétricos.) –