본문으로 건너뛰기
김신건의 로그

너비 우선 탐색 (BFS)

· 수정 · 📖 약 3분 · 1,033자/단어 #algorithm #graph #bfs
BFS, breadth-first search, 너비 우선 탐색, level-order

정의

너비 우선 탐색 (Breadth-First Search, BFS) 는 그래프 G=(V, E) 에서 시작 정점 s 로부터 가까운 정점부터 순서대로 방문하는 알고리즘. 큐 (FIFO) 를 사용해 level order 보장.

무가중 그래프에서 최단 경로 O(V + E) 를 구하는 표준 기법.

문제 상황과 동기

“정점 s 에서 모든 정점까지의 최단 거리 (간선 개수) 를 구하라.”

  • naive DFS: 깊이 우선으로 가면 먼 경로를 먼저 탐색할 수 있음. 최단 보장 안 됨.
  • BFS: 거리 d 인 정점을 모두 방문한 뒤 d+1 로 진행. 먼저 도달한 경로가 항상 최단.

핵심 통찰: 큐 FIFO 순서 = 거리 비감소 순서. 첫 방문 시각 = 최단 거리.

시각화

핵심 아이디어

invariant: 큐에 있는 정점들의 거리는 최대 1 차이. 큐 앞: 거리 d, 큐 뒤: 거리 d 또는 d+1.

dist[s] = 0
큐: [s]

while 큐 not empty:
    u = 큐.pop_front()        # 거리 d
    for v in adj[u]:
        if not visited[v]:
            visited[v] = true
            dist[v] = dist[u] + 1   # 거리 d+1
            큐.push_back(v)

첫 도달 시각이 곧 최단 거리. 다시 방문 불가 (visited[v] 로 막음).

알고리즘

BFS(G, s):
    Q ← new queue
    visited[s] = true
    dist[s] = 0
    parent[s] = null
    Q.enqueue(s)
    
    while Q is not empty:
        u = Q.dequeue()
        for v in G.adj[u]:
            if not visited[v]:
                visited[v] = true
                dist[v] = dist[u] + 1
                parent[v] = u
                Q.enqueue(v)
    
    return dist, parent

구현

// BFS 최단 거리, O(V + E)
#include <bits/stdc++.h>
using namespace std;

vector<int> adj[100005];
int dist[100005];
bool visited[100005];

void bfs(int s) {
  queue<int> q;
  visited[s] = true;
  dist[s] = 0;
  q.push(s);
  
  while (!q.empty()) {
      int u = q.front(); q.pop();
      for (int v : adj[u]) {
          if (!visited[v]) {
              visited[v] = true;
              dist[v] = dist[u] + 1;
              q.push(v);
          }
      }
  }
}

int main() {
  int n, m, s;
  cin >> n >> m >> s;
  for (int i = 0; i < m; i++) {
      int u, v;
      cin >> u >> v;
      adj[u].push_back(v);
      adj[v].push_back(u);
  }
  fill(dist, dist + n + 1, -1);
  bfs(s);
  for (int i = 1; i <= n; i++)
      cout << dist[i] << " ";
  cout << "\n";
}
stdin
5 5 1
1 2
1 3
2 4
3 4
4 5
결과
0 1 1 2 3

복잡도

항목
시간 (인접 리스트)O(V + E)
시간 (인접 행렬)O(V²)
공간O(V) (큐 + visited + dist)
최단 경로 보장✓ (무가중 그래프)

변형

알고리즘변경점
0/1 BFS가중치 0/1 만 있을 때. deque 양쪽 삽입: 0 간선은 push_front
Multi-source BFS시작 정점 여러 개. 모두 큐에 넣고 dist=0 초기화
Flood Fill2D grid 에서 BFS. 상하좌우 4방향 인접
Layer BFS같은 거리 정점을 한 layer 로 묶어 처리 (while 안에 for size)

함정

1. visited 대신 dist 로 판정

dist[v] == -1 로 미방문 체크하면 visited 배열 불필요. 더 간결.

2. 큐 초기화 실수

시작 정점 s 를 큐에 넣고 visited[s] = true 도 꼭 해야 함. 안 하면 무한 루프.

3. 양방향 간선 입력

무향 그래프는 u-v 간선 하나를 adj[u].push(v), adj[v].push(u) 두 번 추가.

4. parent 배열 미관리

경로 복원하려면 parent[v] = u 기록 필요. s 에서 v 까지 경로를 parent 를 따라 역추적.

5. 거리 vs 방문 순서

거리는 간선 개수. 방문 순서 (discovery time) 와 다름. 필요한 값 명확히.

응용 문제 패턴

문제 유형BFS 응용
최단 거리무가중 그래프 s → v 최단 경로
미로 탈출2D grid, (시작) → (도착) 최소 이동 횟수
Flood Fill연결된 영역 색칠 (Paint Bucket)
이분 그래프 판정BFS + 색깔 교대 (0/1 칠하기)
토마토 문제Multi-source BFS, 여러 시작점 동시 확산
뱀과 사다리게임판 그래프, BFS 최소 이동

BOJ 연습 문제

번호제목정답률링크
BOJ 1260DFS와 BFS39.1%kokoa-lab
BOJ 2178미로 탐색44.8%kokoa-lab
BOJ 7576토마토38.6%kokoa-lab
BOJ 1697숨바꼭질32.5%kokoa-lab
BOJ 7569토마토 (3D)37.2%kokoa-lab

참고

이 글의 용어 (4개)
0-1 BFSalgorithm
정의 0-1 BFS 는 간선 가중치가 0 또는 1만 존재하는 그래프에서 최단 경로를 O(V + E) 에 구하는 알고리즘. deque 를 사용해 가중치 0 간선은 앞에, 가중치 1…
그래프 순회 (Graph Traversal)algorithm
정의 그래프 순회 (Graph Traversal) 는 그래프 G=(V, E) 의 모든 정점 V 를 체계적으로 방문하는 알고리즘 패밀리. 대표 구현: 너비 우선 탐색 (BFS), …
깊이 우선 탐색 (DFS)algorithm
정의 깊이 우선 탐색 (Depth-First Search, DFS) 는 그래프 G=(V, E) 에서 갈 수 있는 만큼 깊이 들어가다가 막히면 백트래킹하는 알고리즘. 스택 (LIF…
다익스트라 알고리즘 (Dijkstra's Algorithm)algorithm
정의 다익스트라 알고리즘 (Dijkstra's Algorithm) 은 음이 아닌 가중치 그래프에서 단일 시작점 s 로부터 모든 정점까지의 최단 거리를 찾는 그리디 알고리즘. Ed…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기