python
from collections import deque
def gale_shapley(student_prefs, school_prefs):
"""
学生提出型延迟接受算法。
约定:
1. 学生与学校数量相同。
2. 每个参与者对另一侧均有完整、严格的偏好排序。
3. 每所学校只有一个名额。
"""
students = list(student_prefs)
schools = list(school_prefs)
if len(students) != len(schools):
raise ValueError("本例要求双方人数相同")
n = len(students)
if any(set(order) != set(schools) or len(order) != n
for order in student_prefs.values()):
raise ValueError("学生志愿必须是所有学校的完整排列")
if any(set(order) != set(students) or len(order) != n
for order in school_prefs.values()):
raise ValueError("学校偏好必须是所有学生的完整排列")
rank = {
school: {
student: i
for i, student in enumerate(order)
}
for school, order in school_prefs.items()
}
next_choice = {
student: 0
for student in students
}
held = {
school: None
for school in schools
}
free = deque(students)
while free:
student = free.popleft()
choices = student_prefs[student]
index = next_choice[student]
if index >= n:
continue
school = choices[index]
next_choice[student] += 1
current = held[school]
if current is None:
held[school] = student
elif rank[school][student] < rank[school][current]:
held[school] = student
if next_choice[current] < n:
free.append(current)
else:
if next_choice[student] < n:
free.append(student)
return {
student: school
for school, student in held.items()
if student is not None
}
student_prefs = {
"甲": ["A", "B", "C"],
"乙": ["A", "C", "B"],
"丙": ["B", "C", "A"]
}
school_prefs = {
"A": ["乙", "丙", "甲"],
"B": ["甲", "丙", "乙"],
"C": ["乙", "甲", "丙"]
}
matching = gale_shapley(
student_prefs,
school_prefs
)
for student, school in matching.items():
print(f"{student} → {school}")