Implement prototype(n: int, edges: list[tuple[int, int, int]], source: int) -> list[int | None] and solve with the same signature. Vertices are 0..n-1. Directed integer-weight edges may be negative. Return minimum costs in vertex-index order, using None for unreachable vertices.
Example: (3, [(0,1,4),(0,2,5),(2,1,-3)], 0) returns [0,2,5].
Raise ValueError for n <= 0, invalid source/endpoints, or any source-reachable negative cycle. Unreachable negative cycles do not raise. Prototype: enumerate simple paths and separately inspect reachable cycles. Final: use repeated relaxation and the extra cycle-detection pass. Preserve inputs, including on failure. Return actual integers for finite costs.
Complete the starter code, then run the checks.
Results and errors will appear here.