DFS(깊이우선탐색) / BFS(너비우선탐색)

2020. 2. 8. 02:08코딩테스트

DFS(깊이우선탐색)이란?

  • 그래프 탐색 알고리즘 중 하나로 그래프의 모든 정점을 발견하는 가장 단순하고 고전적인 방법
  • 현재 정점에서 아직 방문하지 않은 인접 정점들을 하나씩 탐색, 더 이상 탐색할 곳이 없다면 이전 상태로 되돌아가는 탐색방법
  • DFS의 구현은 스택 또는 재귀 호출을 이용한다. 
  • DFS는 그래프의 모든 정점을 확인하기 때문에 한정 조건이 있는 문제에서는 비효율적이다.
  • 깊이 제한을 두어 조건이 만족하지 않는 경우를 무시하고 경우를 구하는 알고리즘인 백트래킹(backtracking) 사용

DFS 탐색 순서

 

DFS 구현 방법

1.  그래프의 연결 상태를 나타내는 인접 행렬(adj)과 방문한 정점인지 확인하는(visited)배열이 필요하다.

2.  방문한 정점을 True로 체크, 현재 정점과 연결되어있고 방문한적 없는 정점으로 dfs를 쭉 타고 들어간다.

3.  더 이상 타고 들어갈 정점이 없다면 이전 상태로 돌아온다.

4.  dfsAll()은 그래프의 정점들이 모두 연결되어 있지 않은 경우도 존재하기 때문에 필요하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
def dfs(n):
    
    visited[n] = True
    
    for i in range(len(adj)):
        if adj[n][i] == 1 and visited[i] == False:
            dfs(i)
 
 
def dfsAll():
   #그래프가 연결되지 않은 경우도 있기 때문
    for i in range(len(adj)):
        if visited[i] == False:
            dfs(i)
 
Colored by Color Scripter
                                                                                                          

 

 

dfsAll() 함수가 필요한 이유

 


BFS(너비우선탐색)이란?

  • 깊이 우선 탐색과 함께 가장 많이 사용되는 그래프 탐색 알고리즘
  • 시작점에서 가까운 정점부터 순서대로 방문하는 탐색 알고리즘이다.
  • BFS의 구현은 큐(Queue)를 이용한다. 
  • BFS는 보통 최단 경로 문제에서 많이 사용된다.

BFS 탐색 순서

 

BFS 구현 방법

1.   그래프의 연결 상태를 나타내는 인접 행렬(adj)과 방문할 정점을 체크하는(discovered)배열이 필요하다.

2.  탐색을 시작할 정점을 queue에 넣는다.

3.   현재 정점은 큐에서 꺼내고, 현재 정점과 연결되어 있으며 발견된적 없는 정점을 모두 큐에 넣는다.

4.   큐가 빌 때까지 반복한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def bfs(start):
    
    discovered[start] = True
    queue = [start]
 
    while queue:
        tmp = queue.pop()
        
        for i in range(len(adj)):
            if adj[tmp][i]== 1 and discovered[i] == False:
               queue.append(i)
                discovered[i] = True
Colored by Color Scripter
                                                             

 


 

DFS 와 BFS  차이 / 언제 사용하면 좋을까?

  • 보통 문제들을 보면 DFS와 BFS를 둘 다 사용하여 풀 수 있다.(모든 정점들을 탐색하는 알고리즘)
  • BFS는 최단경로 문제, 가중치 없는 그래프 문제에 적합하다.  > 현재 위치에서 가장 가까운 정점들을 먼저 방문하므로
  • DFS는 가중치 관리가 용이하고 탐색에 대한 제약 조건이 있는 문제에 적합하다. 
  • 또한 DFS는 위상정렬 문제에서도 사용 > DFS의 출력값은 위상정렬 결과의 역순과 같다.

 

 


추천 문제 1) 백준 2468번 안전 영역

https://www.acmicpc.net/problem/2468

 

2468번: 안전 영역

재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는 안전한 영역이 최대로 몇 개가 만들어 지는 지를 조사하려고 한다. 이때, 문제를 간단하게 하기 위하여, 장마철에 내리는 비의 양에 따라 일정한 높이 이하의 모든 지점은 물에 잠긴다고 가정한다. 어떤 지역의 높이 정보는 행과 열의 크기가 각각 N인 2차원 배열 형태로 주어

www.acmicpc.net

이 문제를 풀 때 계속 런타임에러가 났는데 찾아보니 이 문제에서 파이썬으로 DFS을 이용하여 풀 때 무조건 sys.setrecursionlimit()를 추가해야한다. 이 코드는 파이썬 재귀 깊이의 한계치를 늘려준다.  재귀 함수를 사용할 때 런타임 에러가 난다면 써주자.

 

추천 문제 2) 백준 2178번 미로 탐색

https://www.acmicpc.net/problem/2178

 

2178번: 미로 탐색

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

www.acmicpc.net

최소 경로 문제로 DFS를 사용하면 시간 초과 날 확률이 높다. BFS를 이용하자.

 

두 문제 모두 2차원 배열이 인접행렬을 나타내는 것이 아니라 정점 그 자체를 나타낸다. 탐색할 때 현재 위치 기준으로 상하좌우가 연결되어 있는지 모두 판단해야하기 때문에 그 부분을 추가적으로 고려해야한다.

백준 2468번 안전 영역 문제 중

 

DFS / BFS 추천 문제 n선

https://www.acmicpc.net/workbook/view/1833

 

문제집: DFS, BFS 추천문제 (c3171700)

 

www.acmicpc.net

 

References

알고리즘 문제해결 전략2

'코딩테스트' 카테고리의 다른 글

힙(Heap)이란?  (0) 2020.01.18