All Trips

All Trips

Given a directed acyclic graph, return every path from start to end.

allTrips(graph, start, end)

Input format: edges | start | end, edges as a,b pairs. Output each path's nodes joined by -, paths separated by ;, in depth-first order.

Examples

edges a,b a,c b,d c,d, start a, end d   // → "a-b-d;a-c-d"
edges a,b b,c, start a, end c           // → "a-b-c"
edges a,b, start a, end z               // → ""   (no trips)

Walkthrough

Thinking it through

The task is enumerating every path, not finding or counting one. Whenever a problem asks for all sequences satisfying a condition, that's backtracking: build a candidate incrementally, explore forward while options remain, undo the last choice at a dead end or complete answer, try the next.

Why DFS fits naturally

A path is itself a depth-first concept — one unbroken sequence of choices from start to end. DFS from the current node implicitly builds the path taken to get there.

The backtracking mechanic

Maintain a mutable path list. Visiting a node, append it:

  • If it's the destination, the current path is complete — save a copy (not a reference, since the list keeps changing).
  • Otherwise, recurse into each outgoing neighbor, extending the path further.

After exploring a node's possibilities, remove it before returning. This undo step is what makes the shared path list usable across siblings — without it, the path would keep growing across unrelated branches.

Why acyclicity matters

Since the graph has no cycles, there's no infinite recursion risk — every path strictly progresses through the DAG's structure, eventually reaching the destination or running out of edges. Unlike general graph traversal, no visited set is needed within a single path; acyclicity already guarantees termination.

Why this is the right approach

There's no shortcut around visiting every path explicitly, since all of them are requested — you can't compute this with a counting trick the way you could for just the number of paths. DFS-with-backtracking does exactly the necessary work: time proportional to the total length of all output paths, the best possible when the output itself is that large.

main.py
Console
Press Run to execute your code, or Submit to test and complete this problem.