D - 最速配達ルート / Fastest Delivery Route Editorial by admin
Claude 4.5 OpusOverview
This is a shortest path problem from point \(1\) to point \(N\). We find the shortest time using Dijkstra’s algorithm on a weighted graph consisting of one-way roads.
Analysis
Problem Setup
- There are \(N\) points and \(M\) one-way roads
- Each road has a travel time (cost)
- We want to find the shortest time from point \(1\) to point \(N\)
Problems with Naive Approaches
If we try all paths using exhaustive search (DFS/BFS), the number of paths grows exponentially, causing TLE (Time Limit Exceeded) when \(N\) or \(M\) is large.
For example, in a nearly complete graph, the number of paths can be \(O(N!)\).
Solution
We use Dijkstra’s algorithm. This algorithm efficiently solves the single-source shortest path problem when edge weights are non-negative.
In this problem, since \(C_i \geq 1\), all edge weights are positive, making Dijkstra’s algorithm applicable.
Algorithm
Dijkstra’s algorithm works as follows:
- Initialization: Set the distance to the source (point \(1\)) to \(0\), and all other points to \(\infty\)
- Priority Queue: Used to efficiently extract the vertex with minimum distance
- Iteration:
- Extract the vertex \(u\) with minimum distance from the queue
- For each edge \((u, v)\) from \(u\), check if we can update the distance to \(v\)
- If we can update, add the new distance to the queue
Example: N=4, Roads: (1→2, time 3), (1→3, time 5), (2→4, time 2), (3→4, time 1)
Initial state: dist = [∞, 0, ∞, ∞, ∞] (index 0 is unused)
Step 1: Process vertex 1 → dist[2]=3, dist[3]=5
Step 2: Process vertex 2 → dist[4]=3+2=5
Step 3: Process vertex 3 → dist[4]=min(5, 5+1)=5 (no update)
Answer: dist[4] = 5
Complexity
Time Complexity: \(O((N + M) \log N)\)
- Each vertex is extracted from the priority queue at most once
- Each edge is relaxed at most once
- Heap operations are \(O(\log N)\)
Space Complexity: \(O(N + M)\)
- Graph adjacency list: \(O(M)\)
- Distance array: \(O(N)\)
- Priority queue: up to \(O(M)\) (when duplicates exist)
Implementation Notes
Skip Processing:
if d > dist[u]: continue- The same vertex may be added to the queue multiple times with different distances
- Skip if already processed with a shorter distance to avoid unnecessary computation
Early Termination:
if u == N: return- We can terminate immediately once the goal point is finalized (due to Dijkstra’s property, the shortest distance is finalized when first extracted from the queue)
Distance Data Type: Since \(C_i\) can be up to \(10^9\) and there can be up to \(2 \times 10^5\) edges, the shortest distance can be up to about \(2 \times 10^{14}\)
- In Python, there’s no worry about integer overflow, but in other languages, use 64-bit integer types
Using
defaultdict: Prevents errors when accessing non-existent vertices and makes the code more concise
Source Code
import heapq
import sys
from collections import defaultdict
def solve():
input = sys.stdin.readline
N, M = map(int, input().split())
# Build graph with adjacency list
graph = defaultdict(list)
for _ in range(M):
u, v, c = map(int, input().split())
graph[u].append((v, c))
# Dijkstra's algorithm
INF = float('inf')
dist = [INF] * (N + 1)
dist[1] = 0
# (distance, vertex)
pq = [(0, 1)]
while pq:
d, u = heapq.heappop(pq)
# Skip if a shorter path has already been found
if d > dist[u]:
continue
# Terminate when reaching the goal
if u == N:
print(dist[N])
return
for v, cost in graph[u]:
new_dist = d + cost
if new_dist < dist[v]:
dist[v] = new_dist
heapq.heappush(pq, (new_dist, v))
print(dist[N])
solve()
This editorial was generated by claude4.5opus.
posted:
last update: