[PYTHON] 백준 18352 - 특정 거리의 도시 찾기

이또삐(이민혁)·2023년 4월 22일

CODINGTEST

목록 보기
61/96
post-thumbnail

성능 요약

메모리: 161420 KB, 시간: 1404 ms

분류

너비 우선 탐색, 데이크스트라, 그래프 이론, 그래프 탐색

문제 설명

어떤 나라에는 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을 출력한다.


아이디어, 문제풀이

  • 입력 : 단방향, 인접리스트를 통해 구현
  • 출력 : 최단거리를 모두 받아온 뒤, 우리가 입력한 k 와 일치하는 값들만 받아올 수 있도록 한다.

TROUBLE SHOOTING

  • 방향으로 주어지는 bfs 기본문제. 두가지를 알고가면 좋다.
    첫번째로는 배열에 담는법.
    ```python
    graph = [[] for _ in range(n+1)]
    for i in range(m):
        a, b = map(int, input().split())
        graph[a].append(b)
        graph[a].sort()
        graph[b].sort()
    ```
    
    bfs 는 크게 2가지로 나뉘는데, 행렬과 인접리스트다. 이 문제는 방향을 입력값으로 받아올수 있으므로 인접 리스트 형식을 채용해야한다. 위 코드는 graph 에 입력된 값들을 인접 리스트로 구현하는 방법이며, a에 연결된 b들을 넣는 방식으로 적용된다. 한번 프린트 해보면 감을 잡을 수 있다.
    
    두번째는 인접리스트를 구현하는 bfs문.
    
    ```python
    def bfs(graph, start, visit, k):
    
        result = []
        
        que = deque()
        que.append(start)
        visit[start] = 0
        
        while que:
            start = que.popleft()
    
            for i in graph[start]:
                if visit[i] == -1:
                    que.append(i)
                    visit[i] = visit[start] + 1
            
                # if visit[i] == k:
                #     result.append(i)
    
        return visit
    ```
    
    항상 저런 방식으로 이루어지진 않지만, 기본적인 틀은 같으니 왠만하면 외우거나, 최대한 이해하는 방법으로 학습하는게 좋은것 같다.
  • 위 코드상에서 활용하는 visit에 대해서도 깊게 알아두면 앞으로의 문제 풀이에 큰 도움이 된다. 이 코드에서는 visit 을 통해 각 도시에 도달하는 최소값을 담는 용도로 쓰이며, 앞으로도 문제의 의도에 따라 다양하게 사용된다. 아래는 초기에 visit 을 선언하는 방법이다.
    visit = [-1] * (n+1)
    우리가 담아야 하는 입력값의 특성을 잘 살펴보고, 그에 따른 배열 선언을 해주면된다. (여기서는 도시인 n 을 담아야 하기에 n+1 이고, for문 특성상 초과되어 입력받아올 수 있기에, n+1을 해준다 // 인덱스 오류)

코드

#https://www.acmicpc.net/problem/18352
#특정 거리의 도시 찾기
#18352

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

# n = 도시개수 / m = 도로개수 / k = 거리 정보 / x = 출발도시 번호
n, m, k, x = map(int, input().split())

graph = [[] for _ in range(n+1)]
for i in range(m):
    a, b = map(int, input().split())
    graph[a].append(b)
    graph[a].sort()
    graph[b].sort()

# print(graph)

# visit = [0] * n*n
visit = [-1] * (n+1)

def bfs(graph, start, visit, k):

    result = []
    
    que = deque()
    que.append(start)
    visit[start] = 0
    
    while que:
        start = que.popleft()

        for i in graph[start]:
            if visit[i] == -1:
                que.append(i)
                visit[i] = visit[start] + 1
        
            # if visit[i] == k:
            #     result.append(i)

    return visit

visit = bfs(graph, x, visit, k)

ans = []
for i in range(len(visit)):
    if visit[i] == k:
        ans.append(i)

if ans:
    for i in ans:
        print(i)
else:
    print(-1)
profile
해보자! 게임 클라 개발자!

0개의 댓글