Official
D - バス路線の乗り換え / Bus Route Transfers Editorial
by
D - バス路線の乗り換え / Bus Route Transfers Editorial
by
kyopro_friends
今問題は超頂点を用意したグラフ上で 01BFS を行うことで解けます。
各バス停を頂点としてBFSなどを行おうとすると、辺が \(\Theta(N^2)\) 個存在するケースが存在するため解けません。そこで、各バス停に加え「路線 \(i\) のバスに乗車中である」という状態を表す \(M\) 個の頂点を追加した \(N+M\) 頂点のグラフを考えます。
バスに降りるときにコストを払うと考え、
- 路線 \(i\) が通るバス停から「路線 \(i\) に乗車中」へコスト \(0\) の辺
- 「路線 \(i\) に乗車中」から路線 \(i\) が通るバス停へコスト \(1\) の辺
を張ったグラフにおける最小コストが求めるコストに一致します。このグラフの辺の個数は \(2\sum K_i\) 個であるため、全体で \(O(N+M+2\sum K_i)\) 時間でこの問題を解くことができました。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m, s, t;
cin >> n >> m >> s >> t;
s--, t--;
vector<vector<pair<int,int>>>G(n+m);
// 0からN-1がバス停、N+0からN+M-iが路線を表す
for(int i=0; i<m; i++){
int k;
cin >> k;
for(int j=0; j<k; j++){
int a;
cin >> a;
a--;
G[a].push_back({n+i, 0});
G[n+i].push_back({a, 1});
}
}
deque<int>q;
long long INF = 1000000000000000000;
vector<long long>dist(n+m, INF);
dist[s] = 0;
q.push_back(s);
while(q.size() > 0){
int v = q.front(); q.pop_front();
for(auto[vv, c]: G[v]){
if(dist[vv] > dist[v] + c){
dist[vv] = dist[v] + c;
if(c == 0){
q.push_front(vv);
}else{
q.push_back(vv);
}
}
}
}
if(dist[t] == INF){
cout << -1 << endl;
}else{
cout << dist[t] << endl;
}
}
実装例 (Python)
from collections import deque
N, M, S, T = map(int, input().split())
S -= 1
T -= 1
G=[[] for _ in range(N+M)]
# 0からN-1がバス停、N+0からN+M-iが路線を表す
for i in range(M):
K, *A = map(int, input().split())
for a in A:
a -= 1
G[a].append((N+i, 0))
G[N+i].append((a, 1))
INF = 10**18
dist = [INF]*(N+M)
dist[S] = 0
q = deque()
q.append(S)
while len(q) > 0:
v = q.popleft()
for vv, c in G[v]:
if dist[vv] > dist[v] + c:
dist[vv] = dist[v] + c
if c == 0:
q.appendleft(vv)
else:
q.append(vv)
if dist[T] == INF:
print(-1)
else:
print(dist[T])
posted:
last update:
