2
def minNumberOfSemesters(self, n: int, relations: List[List[int]], k: int) -> int:5
# -1 to fix 1-based indexing offset from prompt.6
for pre_req, course in relations:7
graph[course - 1] += 1 << (pre_req - 1)8
out_degree[pre_req - 1] += 19
# Just converts course to its shifted value10
c2shift = [1 << course for course in range(n)]12
goal = 2**n - 1 # will eq course_total once all have been taken.13
queue = collections.deque([(start, 0)])16
# Similar to Bellman-Ford18
# course_total is state. Each bit representing a taken course.19
course_total, steps = queue.popleft()21
for course_num in range(n):22
if (course_total & graph[course_num] == graph[course_num]) and (23
course_total & c2shift[course_num] == 025
available.append(course_num)27
# pre_req courses can unlock others.30
for course_num in available31
if out_degree[course_num]35
for course_num in available36
if out_degree[course_num] == 039
# We only include leaf courses when we have extra space40
if len(pre_reqs) <= k:41
course_total += sum(pre_reqs) + sum(leaves[: k - len(pre_reqs)])42
if course_total == goal:44
if not seen[course_total]:45
queue.append((course_total, steps + 1))46
seen[course_total] = 148
# Trying every combination of the pre_reqs.49
# comb is required here because we can't simply take them all (len(pre_reqs) > k)50
for batch in itertools.combinations(pre_reqs, k):52
t = course_total + diff56
queue.append((t, steps + 1))