백준, 그대, 그머가 되어
TL;DR
- 너비 우선 탐색(BFS)
- 다익스트라 알고리즘(Dijkstra Algorithm)
문제 요약
1. 바꿀 수 있는 문자 간의 관계가 표현되어 있는 그래프에서 주어진 문자를 바꿀 수 있는 최소 횟수를 반환하라.
2. 문자를 바꿀 수 없는 경우에는 -1을 출력한다.
- 문자를 다른 문자로 바꿀 수 있는 관계가 주어진다.
- 이 관계들에서 바꾸기를 원하는 문자를 바꿀 문자로 바꾸는데 걸리는 과정의 최소 횟수를 반환하는 프로그램을 작성하면 된다.
- 각 문자들을 노드로, 바꿀 수 있는 노드들 사이의 관계를 간선의 형태로 그래프로 표현할 수 있다. 이 때, 그래프는 방향성이 없는 무향 그래프이다.
- 노드 사이의 관계를 표현할 때 꺽쇠'<>'가 아닌 괄호'()'를 사용하여 표현한 것을 통해서도 확인할 수 있다.
- 방향성이 있는 그래프의 경우 관계를 표현할 때 <a, b>와 같은 형태로 표현한다. 이는 a -> b이다.
- 양방향 또는 방향이 없는 그래프의 경우는 (a, b)와 같은 형태로 표현한다. 이는 a <-> b이다.
- 간선의 가중치가 1인 최단 경로 찾기 또는 가중치가 없는 무향 그래프의 너비 우선 탐색을 사용해서 문제를 해결할 수 있다.
입출력 형태
풀이
import sys, collections, heapq
a, b = map(int, sys.stdin.readline().split())
n, m = map(int, sys.stdin.readline().split())
answer = 0
graph = collections.defaultdict(list)
for _ in range(m):
x, y = map(int, sys.stdin.readline().split())
graph[x].append((1, y)) # 가중치가 별도로 없기 때문에 1으로 설정
graph[y].append((1, x))
Q = [(0, a)]
dists = collections.defaultdict(int)
while Q:
distance, vertex = heapq.heappop(Q)
if vertex not in dists:
dists[vertex] = distance
for w, v in graph[vertex]:
heapq.heappush(Q, (distance + w, v))
if b in dists:
print(dists[b])
else:
print(-1)
다익스트라 알고리즘(Dijkstra Algorithm)을 사용하여 해결한 방법이다.
각 노드까지 필요한 거리를 저장하는 Q를 선언한다. dists는 각 노드까지 필요한 거리를 저장할 딕셔너리이다.
Q를 순회하며 최소 힙 형태로 그래프를 순회하며 걸리는 거리를 누적한다. 이 연산을 수행하고 나면 dists는 각 노드를 key로 갖고 되고, 시작 노드(문제에서는 바꾸고 싶은 문자)로부터 각 노드까지 필요한 최소 거리가 저장되게 된다.
이 때, 바꾸기를 원하는 문자 노드의 값을 조회해서 출력하면 된다. 만약 바꾸기를 원하는 문자 노드가 dists에 key에 없다면 -1을 출력한다.
다른 풀이
import sys, collections
a, b = map(int, sys.stdin.readline().split())
n, m = map(int, sys.stdin.readline().split())
answer = 0
graph = collections.defaultdict(list)
for _ in range(m):
x, y = map(int, sys.stdin.readline().split())
graph[x].append(y)
graph[y].append(x)
queue = collections.deque([a])
visits = [-1] * (n + 1)
visits[a] = 0
while queue:
node = queue.popleft()
for adj in graph[node]:
if visits[adj] == -1:
visits[adj] = visits[node] + 1
queue.append(adj)
print(visits[b])
간선의 가중치가 따로 주어지지 않았기 때문에 너비 우선 탐색(BFS)로도 문제를 해결할 수 있다.
노드까지 걸리는 최소 횟수를 구하기 위해 각 노드의 길이만큼 방문한 길이를 저장할 리스트 visits를 선언하고 -1로 초기화해준다. -1로 초기화하는 이유는 노드가 존재하지 않을 수 있기 때문이다.
시작 노드(바꾸고 싶은 문자)가 들어있는 큐로부터 순회를 시작한다. 인접 노드를 조회하는데 이 때 만약, visits가 -1의 값, 즉 아직 방문하지 않았다면 해당 값을 현재 노드까지 누적시킨 값에 1을 더하여 저장한다. 그리고 큐에 넣는다.
이렇게 되면 방문한 노드의 visits값은 이전까지 방문하며 누적된 값이 저장되게 되고, -1을 갖지 않기 때문에 추후 방문하지 않게 된다.
큐를 모두 순회하고 나면 visits의 각 노드에 해당하는 인덱스에는 방문한 횟수가 저장되게 된다. 이 때, 바꾸고 싶은 문자 인덱스를 조회하면 원하는 답을 얻을 수 있다.
'개발 > Algorithm' 카테고리의 다른 글
[리트코드] Serialize and Deserialize Binary Tree(python) (0) | 2021.08.20 |
---|---|
[프로그래머스] 위클리 챌린지 2주차(python) (0) | 2021.08.16 |
[백준] 특정 거리의 도시 찾기(python) (0) | 2021.08.05 |
[리트코드] Network Delay Time(python) (0) | 2021.08.01 |
[백준] 막대기(python) (0) | 2021.07.26 |