D - 配達ルートの最短時間 / Shortest Time for Delivery Route 解説 by admin
GPT 5.2 HighOverview
Starting from point \(1\), we find the shortest time to reach point \(N\) while necessarily passing through point \(K\), formulated as a shortest path problem on a weighted undirected graph.
Analysis
The key point of this problem is the condition “must pass through \(K\).” Simply finding the shortest path from \(1 \to N\) does not guarantee that the path passes through \(K\).
The important observation is as follows:
- Any path from \(1\) to \(N\) that passes through \(K\) along the way can be split into a “\(1 \to K\) portion” and a “\(K \to N\) portion.”
- Therefore, the answer is $\( \text{dist}(1,K) + \text{dist}(K,N) \)$ (if we take the shortest path for each portion, the overall path is also shortest).
A naive approach like “try all shortest paths from \(1\) and select only those passing through \(K\)” is impractical due to the enormous number of possible paths. Also, since \(N,M \le 2\times 10^5\), solutions that compute shortest distances from each vertex multiple times will not be fast enough.
Instead, we: - Run Dijkstra’s algorithm from \(1\) as the source to obtain shortest distances to all vertices, giving us \(\text{dist}(1, \cdot)\) - Run Dijkstra’s algorithm again from \(K\) as the source to obtain shortest distances to all vertices, giving us \(\text{dist}(K, \cdot)\)
This immediately gives us the needed \(\text{dist}(1,K)\) and \(\text{dist}(K,N)\).
If either is unreachable, then \(1 \to K \to N\) is naturally impossible, so we output -1.
Algorithm
- Build an undirected graph using an adjacency list (add each road \((u,v,c)\) in both directions).
- Run Dijkstra’s algorithm twice.
- 1st run: Obtain the shortest distance array
dist1from source \(1\). - 2nd run: Obtain the shortest distance array
distKfrom source \(K\).
- 1st run: Obtain the shortest distance array
- If
dist1[K]ordistK[N]is INF (unreachable), output-1. - Otherwise, output
dist1[K] + distK[N].
The reason for using Dijkstra’s algorithm is that all travel times \(C_i\) are positive (\(C_i \ge 1\)), making it efficient for computing weighted shortest paths.
Complexity
- Time complexity: \(O((N+M)\log N)\) run twice, so \(O((N+M)\log N)\)
- Space complexity: \(O(N+M)\) for the adjacency list and distance arrays
Implementation Notes
Make INF sufficiently large: Distances can potentially be the sum of many values up to \(10^9\), so use a large value like
10**30.Discard “stale information” from the priority queue: By including
if d != dist[v]: continue, we ignore elements extracted with outdated distances, preserving the time complexity.Add edges in both directions since the graph is undirected: Don’t forget to add both
graph[u].append((v,c))andgraph[v].append((u,c)).Source Code
import sys
import heapq
def dijkstra(start, graph, n):
INF = 10**30
dist = [INF] * (n + 1)
dist[start] = 0
pq = [(0, start)]
while pq:
d, v = heapq.heappop(pq)
if d != dist[v]:
continue
for to, w in graph[v]:
nd = d + w
if nd < dist[to]:
dist[to] = nd
heapq.heappush(pq, (nd, to))
return dist
def main():
input = sys.stdin.buffer.readline
N, M, K = map(int, input().split())
graph = [[] for _ in range(N + 1)]
for _ in range(M):
u, v, c = map(int, input().split())
graph[u].append((v, c))
graph[v].append((u, c))
dist1 = dijkstra(1, graph, N)
distK = dijkstra(K, graph, N)
INF = 10**30
if dist1[K] >= INF or distK[N] >= INF:
print(-1)
else:
print(dist1[K] + distK[N])
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.2-high.
投稿日時:
最終更新: