D - 混雑する交差点 / Congested Intersection 解説 by admin
Gemini 3.0 Flash (Thinking)Overview
This problem asks us to find the shortest travel time from intersection \(1\) to intersection \(N\) in a graph consisting of \(N\) intersections and \(M\) roads. The difference from a standard shortest path problem is the special cost rule: “passing through an intersection whose degree (number of connected roads) is \(K\) or more costs an additional 1 minute.”
Analysis
1. Organizing the Costs
The time required for travel can be organized as follows: - Traversing one road: always costs 1 minute. - Arriving at intersection \(i\) and then heading to the next intersection (passing through): - If the degree of intersection \(i\) is \(K\) or more, an additional 1 minute is incurred. - However, this additional time does not apply at the starting point (intersection \(1\)) or the destination (intersection \(N\)).
This “additional time when passing through” becomes easier to handle if we interpret it as “a cost incurred when entering that intersection.” Specifically, when moving from intersection \(u\) to intersection \(v\), we define the cost as follows: - When \(v = N\): cost = \(1\) (road only) - When \(v \neq N\) and degree of \(v \ge K\): cost = \(1 + 1 = 2\) (road + additional time) - Otherwise: cost = \(1\) (road only) ※ Even if the degree of the starting intersection 1 is \(K\) or more, no additional time is incurred when “departing” from it, so it does not need to be considered.
2. Why Simple BFS Cannot Solve This
Standard breadth-first search (BFS) can only correctly find shortest paths when all edge costs are equal. In this problem, movement costs are a mix of \(1\) and \(2\), so instead of simple BFS, we need to use Dijkstra’s algorithm.
Algorithm
- Graph Construction and Degree Calculation: Store the graph in adjacency list format, and simultaneously count the degree (number of connected edges) of each vertex.
- Determining Additional Costs: For each intersection \(i \in \{2, \dots, N-1\}\), check whether its degree is \(K\) or more, and store whether additional cost is incurred using a flag or array.
- Shortest Path Search Using Dijkstra’s Algorithm:
- Prepare a priority queue (heap) that manages
(elapsed time, current intersection). - Set the time at the starting point (intersection 1) to 0 and add it to the queue.
- Extract the vertex \(u\) with minimum time \(d\) from the queue, and update the time for each adjacent vertex \(v\):
new_time = d + 1 + (1 if v is an intermediate point and congested, else 0)- If
new_timeis less than the currentdist[v], update it and add to the queue.
- Prepare a priority queue (heap) that manages
- Output the Result:
Output the minimum time to reach intersection \(N\). If it is never reached, output
-1.
Complexity
- Time Complexity: \(O((N + M) \log N)\)
- Degree calculation takes \(O(M)\), and Dijkstra’s algorithm takes \(O((N + M) \log N)\). This runs sufficiently fast for the constraints \(N, M \leq 2 \times 10^5\).
- Space Complexity: \(O(N + M)\)
- \(O(N + M)\) memory is used to store the adjacency list, distance array, and degree array.
Implementation Notes
Fast Input: Since \(N, M\) can be large, in Python using
sys.stdin.read().split()to read all input at once can reduce execution time.Exclusion Conditions for Additional Cost: Do not forget the condition stated in the problem: “no additional time is incurred at the starting point 1 and the destination \(N\).” In code, this can be handled by excluding intersection \(N\) from the check, or by treating \(v=N\) as a special case during cost calculation.
Dijkstra’s Algorithm Basics: Elements extracted from the queue with a cost greater than the already finalized shortest distance should be ignored (
if d > dist[u]: continue) to avoid unnecessary computation.Source Code
import sys
import heapq
def solve():
# Fast input reading using sys.stdin.read().split()
input_data = sys.stdin.read().split()
if not input_data:
return
it = iter(input_data)
try:
N = int(next(it))
M = int(next(it))
K = int(next(it))
except StopIteration:
return
# Building the adjacency list and calculating the degree of each intersection
adj = [[] for _ in range(N + 1)]
degree = [0] * (N + 1)
for _ in range(M):
try:
u = int(next(it))
v = int(next(it))
adj[u].append(v)
adj[v].append(u)
degree[u] += 1
degree[v] += 1
except StopIteration:
break
# extra_cost[v] is 1 if intersection v incurs an additional minute.
# This applies only when "passing through" an intersection, meaning it
# must be an intermediate node in the path. The problem states that
# additional time is not required at the starting intersection (1)
# or the arrival intersection (N).
extra_cost = [0] * (N + 1)
for i in range(2, N):
if degree[i] >= K:
extra_cost[i] = 1
# Dijkstra's algorithm to find the minimum time from intersection 1 to N
# dist[i] stores the minimum time taken to reach intersection i
INF = 10**18
dist = [INF] * (N + 1)
dist[1] = 0
pq = [(0, 1)] # (current_time, current_intersection)
while pq:
d, u = heapq.heappop(pq)
# If a shorter path to u has already been processed, skip this one
if d > dist[u]:
continue
# If we have reached the destination intersection N, output the time
if u == N:
print(d)
return
for v in adj[u]:
# The time to travel along any road is 1 minute.
# If the destination intersection v is an intermediate intersection
# (i.e., v is not N), we add the extra_cost associated with v.
# If v is N, extra_cost[v] is already 0.
new_time = d + 1 + extra_cost[v]
if dist[v] > new_time:
dist[v] = new_time
heapq.heappush(pq, (new_time, v))
# If intersection N is unreachable from intersection 1
print("-1")
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3-flash-thinking.
投稿日時:
最終更新: