문제를 보기 전에 DFS와 BFS 내용을 처음 알아서 먼저 간단히 정리해보려 한다.
두 개념은 대표적인 탐색 알고리즘이다. 탐색 알고리즘이란, 많은 데이터 중에서 원하는 데이터를 찾는 방법을 의미한다. 프로그래밍에서는 주로 그래프와 트리 자료구조 내에서 탐색하는 문제를 자주 다룬다.

DFS란 깊이 우선 탐색 알고리즘이다. 시작 노드에서부터 한 경로를 따라 최대한 깊게 탐색한 후, 다른 경로를 탐색한다. DFS는 스택 혹은 재귀로 구현되는데, 방문한 노드를 스택에 저장하고, 더이상 탐색할 수 없을 때 스택에서 노드를 꺼내어 역순으로 출력한다.
그래프의 구조를 파악하는 데 유용하며, 미로 찾기 등의 문제를 해결하는데 활용된다.

BFS란 너비 우선 탐색 알고리즘이다. 시작 노드에서부터 인접한 노드를 모두 탐색한 후, 다음 노드로 이동한다. BFS는 큐로 구현되는데, 방문한 노드를 큐에 저장하고, 먼저 저장된 노드부터 출력한다.
최단 경로를 찾거나, 노드 간 최단 거리 등을 구하는 데 주로 활용된다.
DFS와 BFS는 조건 내 모든 노드를 방문한다는 점에서 시간 복잡도가 동일하다. 그렇다면 어떤 상황에서 각각을 사용하는지 알아보자.
DFS 활용 예시
BFS 활용 예시
💭 그래프를 DFS로 탐색한 결과와 BFS로 탐색한 결과를 출력하는 프로그램을 작성하시오. 단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문하고, 더 이상 방문할 수 있는 점이 없는 경우 종료한다. 정점 번호는 1번부터 N번까지이다.
입력
첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 양방향이다.
출력
첫째 줄에 DFS를 수행한 결과를, 그 다음 줄에는 BFS를 수행한 결과를 출력한다. V부터 방문된 점을 순서대로 출력하면 된다.
개념으로 공부한 DFS와 BFS 알고리즘을 파이썬 코드로 구현해 볼 수 있는 기본 문제이다.
N, M, V = map(int, input().split())
# 그래프 생성
graph = [[0] * (N + 1) for _ in range(N + 1)]
# 간선 정보 입력
for i in range(M):
a, b = map(int, input().split())
graph[a][b] = graph[b][a] = 1
# 방문 기록 초기화
visited_bfs = [0] * (N + 1)
visited_dfs = [0] * (N + 1)
# DFS 함수 (스택 사용)
def dfs(V):
stack = [V]
while stack:
node = stack.pop()
if visited_dfs[node] == 0:
visited_dfs[node] = 1
print(node, end=" ")
for n in range(N, 0, -1):
if graph[node][n] == 1 and visited_dfs[n] == 0:
stack.append(n)
# DFS 함수 (재귀 사용)
def dfs_재귀(V):
visited_dfs[V] = 1
print(V, end=" ")
for i in range(1, N + 1):
if graph[V][i] == 1 and visited_dfs[i] == 0:
dfs_재귀(i)
# BFS 함수
def bfs(V):
queue = [V]
visited_bfs[V] = 1
while queue:
node = queue.pop(0)
print(node, end=" ")
for i in range(1, N + 1):
if graph[node][i] == 1 and visited_bfs[i] == 0:
queue.append(i)
visited_bfs[i] = 1
# DFS 실행
dfs(V)
print()
# 방문 기록 초기화 후 BFS 실행
visited_dfs = [0] * (N + 1)
bfs(V)