D - 最速配達ルート / Fastest Delivery Route 解説 by admin
GPT 5.2 HighOverview
This is a problem of finding the shortest arrival time from point \(1\) to point \(N\) in a weighted (travel time) directed graph. Since all edge weights are positive, it can be solved using Dijkstra’s algorithm.
Analysis
If we treat each location as a vertex and each road as a directed edge “\(U \rightarrow V\) with cost \(C\)”, this problem is exactly the “shortest path problem from source \(1\) to destination \(N\)”.
Naively “enumerating all paths and taking the shortest” is impractical, as the number of paths explodes with each branch. Also, BFS (Breadth-First Search) finds the shortest path in terms of “number of edges (ignoring costs)”, but since the cost \(C_i\) is not necessarily \(1\) in this problem, it won’t give the correct answer (e.g., if there’s a single edge with cost 100 and a two-edge path with cost 1+1, BFS would choose the single edge).
The key observation is as follows:
- All costs are positive (\(C_i \ge 1\))
→ The property “a confirmed shortest distance is never updated later” holds
→ Dijkstra’s algorithm using a priority queue is applicable, and it runs efficiently even for \(N=10^5, M=2\times10^5\)
Algorithm
We use Dijkstra’s algorithm to find the shortest time dist to each location.
- Build an adjacency list
g[u] = [(v, c), ...](since edges are directed, add only one direction). - Initialize
dist[1] = 0, and all others to a sufficiently large value (INF). - Insert
(0, 1)into a priority queue (min-heap). - Extract
(d, u), the vertex with the current smallest distance, from the queue.- If
d != dist[u], this is outdated information (it was later updated with a shorter distance), so skip it.
- If
- For each edge
(u -> v, w)fromu, computend = d + w.- If
nd < dist[v], updatedist[v] = ndand insert(nd, v)into the queue.
- If
- Repeating this process,
dist[N]will ultimately be the shortest time.- In the code, we terminate early when
u == N(at that pointdist[N]is confirmed), which provides a slight speedup.
- In the code, we terminate early when
Simple example:
- \(1 \to 2\) (5), \(1 \to 3\) (2), \(3 \to 2\) (1)
The shortest path is \(1 \to 3 \to 2\) with \(2+1=3\).
Dijkstra’s algorithm correctly finds this by “first confirming vertex 3 at distance 2 → then updating vertex 2 to distance 3 from there”.
Complexity
- Time complexity: \(O((N+M)\log N)\)
(Each edge relaxation causes at most one update, and each heap operation costs \(\log N\)) - Space complexity: \(O(N+M)\)
(Adjacency list, distance array, and heap)
Implementation Notes
Use an adjacency list (since \(M\) is large, an adjacency matrix is infeasible).
Set
INFto a value sufficiently larger than the maximum possible distance (here,10**30).
The maximum cost is \(10^9\), and a path can have at most \(N-1\) edges, so distances can reach the order of \(10^{14}\).When extracting
(d, u)from the heap, discard it if it doesn’t match the currentdist[u](if d != dist[u]: continue). Without this, the same vertex gets processed multiple times, causing slowdowns.Since the input is large, reading it all at once with
sys.stdin.buffer.read()is faster.Source Code
import sys
import heapq
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
if not data:
return
it = iter(data)
N = next(it)
M = next(it)
g = [[] for _ in range(N + 1)]
for _ in range(M):
u = next(it); v = next(it); c = next(it)
g[u].append((v, c))
INF = 10**30
dist = [INF] * (N + 1)
dist[1] = 0
pq = [(0, 1)]
while pq:
d, u = heapq.heappop(pq)
if d != dist[u]:
continue
if u == N:
break
for v, w in g[u]:
nd = d + w
if nd < dist[v]:
dist[v] = nd
heapq.heappush(pq, (nd, v))
print(dist[N])
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.2-high.
投稿日時:
最終更新: