D - バス路線の乗り換え / Bus Route Transfers 解説 by admin
GPT 5.4 HighOverview
If we consider each bus route as a single vertex and think of “routes sharing the same bus stop can transfer between each other,” then the minimum number of rides can be found as the shortest distance on this route graph.
However, naively adding all edges between routes is too expensive, so the key point is to perform BFS via bus stops.
Discussion
In this problem, riding a bus once allows you to move to “any other bus stop that the route passes through.”
In other words, once you board a route, you can reach all bus stops on that route.
Key Insight 1: Use “routes” rather than “bus stops” as states
For example, if you are riding route \(i\), you can go to any bus stop on that route.
Therefore, rather than tracking “which bus stop am I currently at,” it is more natural to track which route am I currently riding.
- Using route \(i\) = riding that route once
- Two routes sharing the same bus stop can transfer between each other
Thus,
- Starting points: all routes passing through \(S\) (distance \(1\) since this is the first ride)
- Goal: reach any route that passes through \(T\)
and the answer becomes “the number of route transfers.”
Key Insight 2: Explicitly building the route graph is too expensive
Consider making routes into vertices and adding edges between routes that share the same bus stop.
However, if many routes pass through a certain bus stop, that single stop generates a huge number of edges.
For example, if \(d\) routes pass through a certain bus stop, up to \(O(d^2)\) edges are needed among them.
Doing this for all bus stops is far too slow in the worst case.
Key Insight 3: Transition via bus stops “only when needed”
Instead, we only maintain:
- Which bus stops each route passes through
- Which routes pass through each bus stop
and look up transitions only when needed during BFS.
When route \(r\) is dequeued during BFS, we look at each bus stop stop on that route,
and transition to other routes that pass through that stop.
Why used_stop is necessary
Examining the same bus stop multiple times creates significant waste.
For example, if many routes pass through a single bus stop, every time we visit that stop we would redundantly scan the same list of routes.
Therefore, for each bus stop:
- We perform the expansion to other routes only once, the first time.
Since BFS explores in order of increasing distance, the first time we reach a bus stop corresponds to the minimum number of rides to use that stop.
Even if we arrive at the same bus stop later, no better transitions can arise, so processing it once is sufficient.
Routes with only 1 stop cannot be used
According to the problem statement, when riding a route, you must get off at a bus stop “different from the one you are currently at.”
Therefore, routes that pass through only one bus stop cannot actually be used for travel.
In the code, such routes are excluded as transition targets.
Algorithm
We perform BFS as follows.
Preprocessing
Build:
- routes[i]: the list of bus stops that route \(i\) passes through
- stop_to_routes[x]: the list of routes that pass through bus stop \(x\)
At the same time:
- Whether route \(i\) contains \(T\):
contains_t[i] - If route \(i\) contains \(S\), set
dist[i] = 1and enqueue it into the BFS queue
However, when \(S = T\), the destination is reachable without riding any bus, so the answer is \(0\).
BFS
Let dist[i] be “the minimum number of rides needed to board route \(i\).”
- Dequeue route
rfrom the queue - If
rpasses through \(T\), thendist[r]is the answer - Look at each bus stop
stopof router- If
used_stop[stop] = Truealready, skip it - Otherwise, set
used_stop[stop] = True - For every route
nrinstop_to_routes[stop], if it has not been visited yet, setdist[nr] = dist[r] + 1and enqueue it
- If
This explores routes in order of increasing number of rides.
Illustrative Example
For example:
- Route 1: \(\{1, 3, 5\}\)
- Route 2: \(\{5, 7\}\)
- \(S=1, T=7\)
Then:
- We can initially board route 1, so
dist[1] = 1 - From route 1, we can reach bus stop 5
- We can transfer to route 2 which passes through bus stop 5, so
dist[2] = 2 - Route 2 contains \(T=7\)
Therefore the answer is \(2\).
Complexity
Let \(\displaystyle L = \sum_{i=1}^{M} K_i\).
- Time complexity: \(O(N + M + L)\)
- Space complexity: \(O(N + M + L)\)
Reasoning
- The total number of times we scan bus stop lists across all routes is \(O(L)\)
- Each bus stop is expanded at most once due to
used_stop - Each “bus stop ↔ route” correspondence is essentially used at most once
Therefore, the overall algorithm runs in linear time.
Implementation Notes
Handle \(S == T\) first and output \(0\)
Use routes as BFS vertices, with starting routes having distance \(1\)
Use
used_stopto avoid expanding the same bus stop multiple timesRoutes with only one bus stop cannot be used for travel, so do not treat them as transition targets
Since the input size is large, reading all at once with
sys.stdin.buffer.read()is fasterSource Code
import sys
from collections import deque
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
it = iter(data)
N = next(it)
M = next(it)
S = next(it)
T = next(it)
if S == T:
print(0)
return
routes = [[] for _ in range(M)]
stop_to_routes = [[] for _ in range(N + 1)]
contains_t = [False] * M
dist = [-1] * M
q = deque()
for i in range(M):
k = next(it)
arr = [0] * k
if k >= 2:
has_s = False
has_t = False
for j in range(k):
a = next(it)
arr[j] = a
stop_to_routes[a].append(i)
if a == S:
has_s = True
if a == T:
has_t = True
contains_t[i] = has_t
if has_s:
dist[i] = 1
q.append(i)
else:
arr[0] = next(it)
routes[i] = arr
used_stop = [False] * (N + 1)
used_stop[S] = True
while q:
r = q.popleft()
d = dist[r]
if contains_t[r]:
print(d)
return
for stop in routes[r]:
if used_stop[stop]:
continue
used_stop[stop] = True
for nr in stop_to_routes[stop]:
if dist[nr] == -1:
dist[nr] = d + 1
q.append(nr)
print(-1)
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.4-high.
投稿日時:
最終更新: