The base implementation was fine, I went with Kahn's and got through it cleanly.
Start by clearly defining the problem and the three variants, then walk through each with a concrete algorithm, data structure choices, and runtime analysis. Emphasize the trade-offs between using Kahn's algorithm (BFS) versus DFS, and how tie-breaking and enumeration affect complexity. Conclude by discussing practical considerations like cycle detection and scalability.
Pro tip: Mention that Kahn's algorithm naturally supports tie-breaking with a priority queue, but for enumeration, backtracking with in-degree tracking is essential; also note that the number of topological orderings can be exponential, so output-sensitive complexity is key.
Confirm that the graph is a DAG, discuss input representation (adjacency list), and define what 'tie-breaking' means (e.g., lexicographic order of node labels).
Use Kahn's algorithm (BFS with in-degree tracking) or DFS with post-order reversal. State runtime: O(V+E) for both.
Replace the queue in Kahn's algorithm with a min-heap (or priority queue) to always pick the smallest available node. Runtime becomes O(V log V + E log V) or O(E + V log V) depending on implementation.
Use backtracking: at each step, choose any node with in-degree 0, mark it as visited, decrement in-degrees of its neighbors, recurse, then backtrack. Runtime is O(V * (V+E) * K) where K is the number of orderings, or more precisely O((V+E) * K) with careful implementation.
Discuss cycle detection, memory usage, and when enumeration is feasible (small K). Mention that tie-breaking adds log factor but ensures deterministic output.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.