출처: 구름 알고리즘 먼데이 챌린지 7주차
문제
구름이가 사는 구름 나라는 N개의 섬으로 이루어져 있다. 각 섬에는 1부터 N까지의 번호가 붙어 있고, 구름 나라는 사람들이 섬과 섬 사이를 편하게 이동할 수 있도록 다리를 M개 설치했다.
설치된 다리들은 아래의 특징들을 만족한다.
- 모든 다리는 단방향으로만 이동 가능하다.
- 다리가 잇는 두 섬은 항상 다른 섬이다.
구름이는 현재 K번 섬에 있고, 다른 섬들을 둘러본 뒤 다시 K번 섬으로 돌아오려고 한다. 그렇지만 오래 돌아다니는 것은 피곤한 일이기 때문에, 구름이는 최소한의 섬만 거치는 경로를 택할 것이다. 구름이를 도와 최소 몇 개의 섬을 거쳐서 원래 구름이가 있던 섬으로 돌아올 수 있을지 알아보자.
단, 구름이는 K번 섬 이외에 최소 하나 이상의 다른 섬을 방문해야 한다.
예제 설명
첫 번째 예제에서는 아래와 같이 구름 나라의 섬과 다리가 배치되어 있다. 구름이는 현재 4번 섬에 있다.
4번 섬에서 출발한 구름이는 2번과 5번 섬으로 이동할 수 있다.
2번 섬으로 이동한 구름이는 더 이상 이동할 수 없지만, 5번 섬으로 이동한 구름이는 3번과 1번 섬을 거쳐서 다시 4번 섬으로 돌아올 수 있다.
이 경우 총 4개의 섬을 통과했다.
두 번째 예제에서는 아래와 같이 구름 나라의 섬과 다리가 배치되어 있다. 구름이는 현재 4번 섬에 있다.
4번 섬에서 출발한 구름이는 2번 섬으로 이동할 수 있고, 2번 섬에서는 다른 섬으로 이동할 수 없다. 따라서 다시 4번 섬으로 돌아오는 것은 불가능하고, -1 을 출력해야 한다.
입력
첫째 줄에 섬의 개수 N (2<=N<=10,000)과 다리의 개수 M(1<=M<=50,000)과 구름이가 있는 섬의 번호 K(1<=K<=N)가 공백을 두고 주어진다.
둘째 줄부터 M개의 줄에 걸쳐서 a,b (1 <= a,b <= N, a!=b) 형태로 다리의 상태가 주어진다. 이는 a번 섬에서 b번 섬으로 갈 수 있는 다리가 존재함을 의미한다. 동일한 시작 섬과 도착 섬을 잇는 다리가 주어지지 않는다.
입력에서 주어지는 모든 수는 정수이다.
출력
k번 섬에서 출발한 구름이가 최소 몇 개의 섬을 거쳐서 다시 k번 섬으로 도착할 수 있는지 출력하시오. 만약 구름이가 다시 돌아올 수 없다면 -1을 출력하시오.
입력 | 출력 |
5 6 4 1 2 1 4 3 1 4 2 4 5 5 3 |
4 |
5 6 4 1 2 1 3 3 2 4 2 5 1 5 4 |
-1 |
풀이
최소 길이의 사이클을 찾는다 => BFS
(1) 인접리스트 graph와 (2) 해당 노드에 몇 번을 거쳐 도착하는 지를 나타내는 1차원 리스트 visited(0이면 아직 방문 안함) 를 사용
* visited를 False로 초기화하고 방문시 True로 업데이트하면 k 노드는 처음에 방문하므로 이후에 방문 여부를 체크할 수 없음
'''
1번부터 N번까지의 섬
섬 사이의 M개의 다리 (N개 노드, M개 간선, 단방향)
K번째 섬에서 K번째 섬으로 오는 최소한의 거리 (하나 이상의 다른 섬) / 못 돌아오면 -1
idea: 최단 경로를 찾는 bfs
'''
#import sys
#sys.stdin = open('./quiz/input2.txt', 'r')
from collections import deque
# 1. 입력 받기
n, m, k = map(int, input().split())
graph = [[] for _ in range(n+1)] # 인접리스트
for _ in range(m):
a, b = map(int, input().split())
graph[a].append(b)
#print(graph)
# 2. BFS
q = deque()
visited = [ 0 for _ in range(n+1)]
# 초기 상태 지정
q.append(k)
visited[k] = 0
while q:
v = q.popleft()
for i in graph[v]:
if visited[i] == 0:
visited[i] = visited[v] + 1
q.append(i)
if i == k:
break
if visited[k] == 0:
print(-1)
else:
print(visited[k])
다른 풀이
노드간 연결 정보를 저장할 때 인접행렬이 아닌 defaultdict 사용
'''
1번부터 N번까지의 섬
섬 사이의 M개의 다리 (N개 노드, M개 간선, 단방향)
K번째 섬에서 K번째 섬으로 오는 최소한의 거리 (하나 이상의 다른 섬) / 못 돌아오면 -1
idea: 최단 경로를 찾는 bfs
'''
#import sys
#sys.stdin = open('./quiz/input2.txt', 'r')
from collections import defaultdict
from collections import deque
# 1. 입력 받기
n, m, k = map(int, input().split())
graph = defaultdict(list)
for i in range(m):
a, b = map(int, input().split())
graph[a].append(b)
# 2. BFS
q = deque()
visited = [ 0 for _ in range(n+1)]
# 초기 상태 지정
q.append(k)
visited[k] = 0
while q:
v = q.popleft()
for i in graph[v]:
if visited[i] == 0:
visited[i] = visited[v] + 1
q.append(i)
if i == k:
break
if visited[k] == 0:
print(-1)
else:
print(visited[k])
'코테 공부 > 그 외 사이트' 카테고리의 다른 글
[Python/백트래킹] 1244. [S/W 문제해결 응용] 2일차 - 최대 상금 (0) | 2022.11.28 |
---|---|
[Python] 1206. [S/W 문제해결 기본] 1일차 - View (0) | 2022.11.25 |
[Python/DFS] 2.퍼져나가는 소문 / 그래프 탐색 (0) | 2022.11.21 |
[Python] 1.UXUI 디자이너/ lambda, sorted (0) | 2022.11.21 |
[Python/BFS] 이코테 미로탈출 (중요. 기본기) (0) | 2022.08.17 |