[파이썬] 백준 2021 : 최소 환승 경로 (골드2)
2021번: 최소 환승 경로
첫째 줄에 역의 개수 N(1≤N≤100,000), 노선의 개수 L(1≤L≤100,000)이 주어진다. 다음 L개의 줄에는 각 노선이 지나는 역이 순서대로 주어지며 각 줄의 마지막에는 -1이 주어진다. 마지막 줄에는 출발
www.acmicpc.net
문제
풀이
0. 방향성 생각
- 필요한 노드는 환승역, 출발점, 시작점이다.
- 지나는 역의 개수가 2개 이상인 점과 출발점, 시작점만을 추출한다.
- BFS를 통해 탐색하고, 이동하면서 노선이 바뀌면 체크해주기
1. 입력
from collections import deque,defaultdict
import sys
input = lambda : sys.stdin.readline().rstrip()
n,l = map(int,input().split())
table = {i:0 for i in range(1,n+1)}
lines = [[] for _ in range(l+1)]
for line in range(1,l+1):
lines[line].extend(list(map(int,input().split()))[:-1])
for station in lines[line]:
table[station] += 1
start,end = map(int,input().split())
- table 딕셔너리를 만들어서 지하철 라인이 지나갈 때 마다 +1을 해준다.
2. 필요한 노드만 추출
new_lines = [[] for _ in range(l+1)]
for line in range(1,l+1):
for station in lines[line]:
if table[station] > 1 or station == start or station == end:
new_lines[line].append(station)
- 환승역이랑 시작점, 끝점만 추출한다.
3. graph 연결, 노선 연결정보 move 정의
move = defaultdict(int)
graph = [[] for _ in range(n+1)]
for line,new_line in enumerate(new_lines):
count = len(new_line)
if count > 1:
for i in range(count-1):
a,b = new_line[i],new_line[i+1]
graph[a].append(b)
graph[b].append(a)
move[(a,b)] = line
move[(b,a)] = line
- a,b로 가는 노선정보를 move에 추가한다.
- graph 연결요소를 추가한다.
4. BFS
inf = 1e6
visit = [inf]*(n+1)
visit[start] = 0
q = deque()
for nx in graph[start]:
q.append((start,0,move[(start,nx)]))
while q:
x,t,line = q.popleft()
if x == end:
break
if t > visit[x]:
continue
for nx in graph[x]:
if move[(x,nx)] == line: nt = t
else: nt = t+1
if nt < visit[nx]:
q.append((nx,nt,move[(x,nx)]))
visit[nx] = nt
print(visit[end]) if visit[end] != inf else print(-1)
- 현재 타고있는 노선 line에서 다른 노선으로 변경될 때, 환승 카운트 t를 늘려준다.
전체코드
from collections import deque,defaultdict
import sys
input = lambda : sys.stdin.readline().rstrip()
n,l = map(int,input().split())
table = {i:0 for i in range(1,n+1)}
lines = [[] for _ in range(l+1)]
for line in range(1,l+1):
lines[line].extend(list(map(int,input().split()))[:-1])
for station in lines[line]:
table[station] += 1
start,end = map(int,input().split())
new_lines = [[] for _ in range(l+1)]
for line in range(1,l+1):
for station in lines[line]:
if table[station] > 1 or station == start or station == end:
new_lines[line].append(station)
move = defaultdict(int)
graph = [[] for _ in range(n+1)]
for line,new_line in enumerate(new_lines):
count = len(new_line)
if count > 1:
for i in range(count-1):
a,b = new_line[i],new_line[i+1]
graph[a].append(b)
graph[b].append(a)
move[(a,b)] = line
move[(b,a)] = line
inf = 1e6
visit = [inf]*(n+1)
visit[start] = 0
q = deque()
for nx in graph[start]:
q.append((start,0,move[(start,nx)]))
while q:
x,t,line = q.popleft()
if x == end:
break
if t > visit[x]:
continue
for nx in graph[x]:
if move[(x,nx)] == line: nt = t
else: nt = t+1
if nt < visit[nx]:
q.append((nx,nt,move[(x,nx)]))
visit[nx] = nt
print(visit[end]) if visit[end] != inf else print(-1)
코멘트
풀고보니까 진짜 못푼듯. 변수할당도 쓸데없이 많이했고, 결과론적으로 다른 점들을 추출할 필요가 없었음.
저번에 풀었던 죽음의 비 문제에서 필요없는 노드들을 생각하지 않는 발상에서 접근.
그 때는 좌표 정보를 바로 맨하탄 거리로 치환해서 금방 얻을 수 있었다면, 이번에는 많은 데이터에 대해서 순회를 여러번 해버리니 시간이 오래걸렸다.
입력정보 보고 잘 생각해서 선택하기.
'Algorithm > Graph' 카테고리의 다른 글
[파이썬] 백준 1944 : 복제 로봇 (골드1) (0) | 2023.12.19 |
---|---|
[파이썬] 백준 1194: 달이 차오른다, 가자. (골드1) (0) | 2023.12.19 |
[파이썬] 백준 5719 : 거의 최단 경로 (플레5) (0) | 2023.12.19 |
[파이썬] 백준 5213 : 과외맨 (골드2) (0) | 2023.12.17 |
[파이썬] 백준 16441 : 아기돼지와 늑대 (골드3) (0) | 2023.12.17 |
[파이썬] 백준 2887 : 행성터널 (플레5) (0) | 2023.12.16 |
[파이썬] 백준 16933 : 벽 부수고 이동하기 3 (골드1) (0) | 2023.12.16 |
댓글