python, pyTorch/코딩테스트-파이썬

DFS BFS 모음 (BOJ 1260, 11725, 2667)

zooyeonii 2022. 1. 8. 14:25

DFS와 BFS는 이진탐색보다 유독 문제에서 마주쳤을 때 당황스러웠다. DFS나 BFS로 풀 수 있는 문제를 모아서 리뷰해봤다. 

1. DFS와 BFS

DFS와 BFS 복습을 위한 문제^^*

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

 

1260번: DFS와 BFS

첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사

www.acmicpc.net

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from collections import deque
N, E, start = map(int, input().split())
arr = []
graph = [[] for _ in range(N+1)]
 
for i in range(E):
    arr.append(list(map(int, input().split())))
    idx1 = arr[i][0]
    idx2 = arr[i][1]
    graph[idx1].append(idx2)
    graph[idx2].append(idx1)
 
for i in range(len(graph)):
    graph[i].sort()
 
visit = [False]*(N+1)
visited = [False]*(N+1)
def dfs(graph,v,visit):
    visit[v] = True
    print(v, end=' ')
    for i in graph[v]:
        if not visit[i]:
            dfs(graph, i, visit)
 
def bfs(graph, start, visited):
    queue = deque([start])
    visited[start] = True
    while queue:
        v = queue.popleft()
        print(v, end=' ')
        for i in graph[v]:
            if not visited[i]:
                queue.append(i)
                visited[i] = True
 
 
dfs(graph, start, visit)
print()
bfs(graph, start, visited)
cs

 

1. 입력으로 node의 수, edge의 수, 시작 노드를 받는다. 
더블리스트의 그래프로 만들어준다. 

2. DFS는 시작점(start)을 visit=True하고, start 노드와 연결된 노드가 visit=False라면, dfs를 실행한다. (반복)

3. BFS는 시작점(start)을 queue에 넣은 후, visited = True하고, queue에서 popleft()를 하여 나온 노드와 연결된 모든 노드 중 visited=False인 노드들을 queue에 넣는다. 그리고 visited=True로 바꿔준다. 

2. 트리의 부모 찾기

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

 

11725번: 트리의 부모 찾기

루트 없는 트리가 주어진다. 이때, 트리의 루트를 1이라고 정했을 때, 각 노드의 부모를 구하는 프로그램을 작성하시오.

www.acmicpc.net

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from collections import deque
= int(input())
arr = []
graph = [[] for _ in range(N+1)]
 
for i in range(N-1):
    arr.append(list(map(int, input().split())))
    idx1 = arr[i][0]
    idx2 = arr[i][1]
    graph[idx1].append(idx2)
    graph[idx2].append(idx1)
 
visited = [False]*(N+1)
 
def bfs(graph, start, visited):
    queue = deque([start])
    visited[start] = True
    parent = 0
    while queue:
        v = queue.popleft()
        parent = v
        for i in graph[v]:
            if not visited[i]:
                queue.append(i)
                visited[i] = v
 
bfs(graph, 1, visited)
for i in range(2, N+1):
    print(visited[i])
cs

1. 입력으로 노드의 수 (N), 엣지(N-1)를 받는다. 
더블리스트의 그래프로 만들어주고, DFS와 달리 정렬할 필요없다. 

2. 코드는 BFS로 풀었는데, visited를 True, False 대신 부모 노드의 ID로 기록한다. 

3. 단지번호붙이기

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

 

2667번: 단지번호붙이기

<그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여

www.acmicpc.net

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
= int(input())
graph = []
for i in range(n):
    graph.append(list(map(int, input())))
 
visited = [[False for _ in range(n)] for _ in range(n)]
count = 1
 
#이동할 네 방향
dx = [-1010]
dy = [010-1]
 
def dfs(x,y):
    global count
    for i in range(4): #각 지점의 북,동,남,서(시계방향) 살핌.
        nx = x+dx[i]
        ny = y+dy[i]
        if 0<=nx<and 0<=ny<n:
            # 그래프에서 1인데 아직 방문 안한 곳
            if visited[nx][ny]==False and graph[nx][ny]==1:
                visited[nx][ny] = True
                count+=1
                dfs(nx, ny)
 
total = 0
result = []
for i in range(n):
    for j in range(n):
        if visited[i][j] == False and graph[i][j]==1:
            visited[i][j] = True
            total += 1
            dfs(i, j) #단지 순회해서 count했음.
            result.append(count)
            count = 1 #count 다시 초기화해줌.
 
result.sort()
print(total)
for i in result:
    print(i)
cs

 

1. DFS로 푸는데, 문제가 각 단지가 몇개인지 기록해야한다는 것이었다. global 변수를 사용해서, dfs 함수 밖에서 변수를 초기화 해준다. (단지 바뀔 때마다 리셋)

2. 원래 dfs 함수 내부에서 재귀함수로 dfs(x+1, y) dfs(x, y+1) 이러한 방식으로 상,하,좌,우를 탐색하는데 여기서는 dx와 dy를 지정해준다. 처음엔 dx = [-1, 0, 1, 0]이 graph[x][y]에서 상, 하를 의미한다는 것을 이해하지 못했다. 하지만 행렬을 그려놓고 생각해보니, graph[x-1][y]이 북, graph[x][y+1]이면 동쪽을 가리킨다는 것을 깨달았다..다 스승님 덕분이다(최고)

3. 최종적으로 단지의 개수를 세기 위해 변수 total, dfs 함수 내에서 각 지점 주변을 탐색하여 count를 구할 수 있다. 이를 리스트에 저장해놓으면 각 단지 내 아파트 수를 기록할 수 있다.