99클럽 코테 스터디 10일차 TIL + BFS

gahyunkim·2024년 11월 6일

항해99

목록 보기
10/34
post-thumbnail

백준 18352번 특정 거리의 도시 찾기

시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초256 MB61103204561315631.608%

문제

어떤 나라에는 1번부터 N번까지의 도시와 M개의 단방향 도로가 존재한다. 모든 도로의 거리는 1이다.

이 때 특정한 도시 X로부터 출발하여 도달할 수 있는 모든 도시 중에서, 최단 거리가 정확히 K인 모든 도시들의 번호를 출력하는 프로그램을 작성하시오. 또한 출발 도시 X에서 출발 도시 X로 가는 최단 거리는 항상 0이라고 가정한다.

예를 들어 N=4, K=2, X=1일 때 다음과 같이 그래프가 구성되어 있다고 가정하자.

이 때 1번 도시에서 출발하여 도달할 수 있는 도시 중에서, 최단 거리가 2인 도시는 4번 도시 뿐이다.  2번과 3번 도시의 경우, 최단 거리가 1이기 때문에 출력하지 않는다.

[입력]

첫째 줄에 도시의 개수 N, 도로의 개수 M, 거리 정보 K, 출발 도시의 번호 X가 주어진다. (2 ≤ N ≤ 300,000, 1 ≤ M ≤ 1,000,000, 1 ≤ K ≤ 300,000, 1 ≤ X ≤ N) 둘째 줄부터 M개의 줄에 걸쳐서 두 개의 자연수 AB가 공백을 기준으로 구분되어 주어진다. 이는 A번 도시에서 B번 도시로 이동하는 단방향 도로가 존재한다는 의미다. (1 ≤ AB ≤ N) 단, A와 B는 서로 다른 자연수이다.

[출력]

X로부터 출발하여 도달할 수 있는 도시 중에서, 최단 거리가 K인 모든 도시의 번호를 한 줄에 하나씩 오름차순으로 출력한다.

이 때 도달할 수 있는 도시 중에서, 최단 거리가 K인 도시가 하나도 존재하지 않으면 -1을 출력한다.

문제 해석하기

도시 x로부터 출발해서 도달할 수 있는 모든 도시 중에서 최단 거리가 정확히 K인 도시들의 번호를 출력하고자 한다면, 너비 우선 탐색을 사용하는 것이 좋겠다는 생각을 함.

  • n,m,k,x로 각각의 값을 받아준다. 여기서 입력되는 값이 최대 1,000,000까지 커질 수 있으므로, 입력 속도를 높이기 위해 input() 대신 sys.stdin.readline()을 사용하는 것이 좋다고 판단함
  • graph = [[] for _ in range(n+1)] 형태로 인접 리스트를 사용하여 정점과 정점 사이의 간선을 넣어줄 수 있는 그래프를 구현해준다.
  • 단방향임을 유의하면서, 정점 사이의 간선을 추가해주도록 한다.
    • u,v = map(int,input().split()) 을 통해 정점과 간선을 입력받고
    • 해당하는 간선은 단방향이므로 ,graph[u].append(v) 만 사용해주도록 한다.
  • 거리 정보를 초기화한다
    • distance 배열을 이용해서 각 도시에 도달하는 최단 거리를 기록해준다.
    • 배열을 -1로 초기화 해서 아직 방문하지 않은 도시임을 나타내어 준다.
  • 너비우선 탐색을 할 예정이기 때문에 bfs 알고리즘을 사용해준다.
    • x로부터 다른 도시로의 최단 거리를 구해준다.
    • queue를 통해서 현재 도시와 연결된 도시를 찾고, 방문하지 않은 도시에 대해서만 distance값을 +1해준다.
  • distance 배열에서 최단거리가 k 인 도시들을 출력한다.
    • 만약에 k 인도시가 없다면, -1을 출력해서 해당 도시가 없음을 나타내준다.

import sys
from collections import deque
input = sys.stdin.readline

n, m, k, x = map(int, input().split())

# 그래프 초기화
graph = [[] for _ in range(n + 1)]

# 간선 정보 입력
for _ in range(m):
    u, v = map(int, input().split())
    graph[u].append(v)  # 단방향 간선 추가

# 거리 초기화
distance = [-1] * (n + 1)
distance[x] = 0  # 시작하는 도시의 거리는 0으로 설정

# BFS 탐색
queue = deque([x])
while queue:
    current = queue.popleft()
    
    for i in graph[current]:
        if distance[i] == -1:
            distance[i] = distance[current] + 1
            queue.append(i)

# 거리 k인 도시 출력
found = False
for i in range(1, n + 1):
    if distance[i] == k:
        print(i)
        found = True

# 거리가 k인 도시가 없는 경우
if not found:
    print(-1)


오늘의 회고

어제 정리했던 BFS 문제들 덕분에 문제를 읽자마자 최단 거리 문제임을 파악하고 BFS를 사용해야 함을 빠르게 알 수 있었다. BFS 알고리즘을 사용하는 방식은 같지만, 출력 과정과 목표가 조금씩 달라지기 때문에 각 상황에 맞게 BFS 구현을 더 세심히 고민해야겠다는 생각이 들었다.

0개의 댓글