https://www.acmicpc.net/problem/22868
22868번: 산책 (small)
첫 번째 줄에는 정점의 개수 $N$과 두 정점 사이를 잇는 도로의 개수 $M$이 공백으로 구분되어 주어진다. 두 번째 줄부터 $M + 1$ 번째 줄까지 정점 $A, B$가 공백으로 구분되어 주어진다. 정점 $A$와
www.acmicpc.net
S -> E로의 최단거리를 구해 해당 경로를 위해 사용된 정점을 제외하고 E -> S로의 최단거리를 구해주면 된다. 간선의 길이가 1으로 고정이 되어있으므로 BFS를 2번 돌려서 풀이가 가능합니다. 이 문제의 포인트는 최단 경로를 위해 사용된 노드들을 기록해야하는데 이는 S -> E를 위한 BFS를 돌릴 때 현재 노드의 이전 노드를 기록해두면 됩니다. 다음 노드를 방문하려고 하는데 prev가 기록되어 있으면 이미 방문한 노드이므로 방문하지 않으면 됩니다. 각 노드에 연결된 노드들을 정렬해서 저장해 놓은 상태에서 BFS_with_prev를 돌리면 자연스럽게 사전순으로 경로가 지정되게 됩니다. 다음으로는 prev를 이용하여 S -> E 최단 경로를 위해 사용된 정점들을 방문처리를 해두고 E -> S BFS를 통해 얻은 최단 경로의 길이와 합해주면 정답이 됩니다.
import sys
from collections import defaultdict, deque
# sys.stdin = open("input.txt", "r")
input = sys.stdin.readline
n, m = tuple(map(int, input().split()))
graph = defaultdict(list)
# 그래프 입력 받기
for _ in range(m):
start, end = tuple(map(int, input().split()))
graph[start].append(end)
graph[end].append(start)
# s: 시작, e: 목적지
s, e = tuple(map(int, input().split()))
# 그래프와 연결되어 있는 정점들 정렬
for key in graph.keys():
graph[key].sort()
# 현재 i번 노드를 방문하는 직전 노드를 저장해둔다.
# 각 노드와 연결되어 있는 노드들을 정렬해두었기 때문에 여러 노드들에서 방문이 가능하더라도 가장 숫자가 작은 노드를 저장하게 된다.
prev = [0] * (n + 1)
global_visited = [False] * (n + 1)
# prev를 기록하는 BFS
def bfs_with_prev(start, dest):
prev[start] = start
q = deque([(0, start)])
while q:
d, cur_node = q.popleft()
# 목적지에 도달하면 최단 경로 리턴
if cur_node == dest:
return d
for next_node in graph[cur_node]:
# 직전 노드가 없으면 방문한다.
# 그리고 prev에 직전 노드를 저장해둔다.
if prev[next_node] == 0:
prev[next_node] = cur_node
q.append((d + 1, next_node))
return -1
# 일반 BFS
# visited에는 S -> E로 이동할 때 사용된 노드들이 방문처리되어있다.
def bfs(start, dest, visited):
q = deque([(0, start)])
visited[start] = True
while q:
d, cur_node = q.popleft()
if cur_node == dest:
return d
for next_node in graph[cur_node]:
# 방문한 적이 없으면 방문한다.
if not visited[next_node]:
visited[next_node] = True
q.append((d + 1, next_node))
return -1
# S -> E까지의 경로 길이 및 prev 기록
answer = bfs_with_prev(s, e)
# 도착까지 최단 거리 + 사전순 경로에 방문 처리를 해준다.
cur = e
while prev[cur] != cur:
global_visited[cur] = True
cur = prev[cur]
# E -> S 경로 길이를 더하여 답을 출력한다.
print(answer + bfs(e, s, global_visited))
'문제 해결 > BOJ' 카테고리의 다른 글
[백준] 탑 보기 (0) | 2023.02.11 |
---|---|
[백준] A를 B로 (0) | 2023.02.10 |
[백준] 원 이동하기 2 (0) | 2023.02.09 |
[백준] 뉴스 전하기 (0) | 2023.02.08 |
[백준] 벽 부수고 이동하기 (0) | 2023.02.07 |