문제 풀이
문제 탐색하기
너비 우선 탐색(BFS, Breadth-First Search) ?
그래프 탐색 알고리즘으로, 너비를 우선으로 하여 탐색을 진행합니다. 시작 노드에서 가까운 노드를 우선적으로 탐색하며, 동일 레벨에 있는 노드를 모두 탐색한 후 다음 레벨로 넘어가는 방식입니다. BFS는 일반적으로 큐(Queue) 자료 구조를 사용하여 구현합니다.
BFS의 동작 원리
- 시작 노드를 큐에 삽입하고 방문 처리를 합니다.
- 큐에서 노드를 하나씩 꺼내 해당 노드의 이웃 노드를 모두 큐에 추가합니다. 추가할 때 이웃 노드가 방문되지 않은 경우만 추가합니다.
- 위 과정을 큐가 빌 때까지 반복합니다.
BFS의 주요 특징
- 시간 복잡도: O(V + E) (V: 정점 수, E: 간선 수)로 그래프의 모든 노드를 탐색합니다.
- 장점: 최단 경로를 찾는 문제에 적합하며, 경로 탐색에서 DFS와 달리 특정 노드까지의 최단 거리를 보장합니다.
- 단점: DFS보다 메모리 사용량이 많을 수 있습니다. 넓은 범위를 우선 탐색하므로 큐에 많은 노드가 쌓일 수 있기 때문입니다.
BFS의 활용 예시
BFS는 최단 경로 찾기, 레벨 순회, 최소 이동 비용 계산 등 최단 거리나 계층 구조 탐색이 필요한 문제에 적합합니다.
BFS 알고리즘을 활용하여 문제 설계하기
문제에 주어진 예제를 이용하여 BFS 알고리즘을 이해하고 문제 풀이를 설계해보겠습니다.
예제는 아래와 같습니다.
5 5 1 (정점 N : 5 / 간선M : 5 / 시작 점 R : 1 )
1 4
1 2
2 3
2 4
3 4
정점 1하고 인접한 2, 4를 탐색하며 처음 방문하는 노드이기 때문에 큐에 2, 4를 추가합니다.
더 이상 방문할 노드가 없는 경우 dequeue 하여 나오는 정점에서 재 탐색합니다.
정점 2는 3하고 4를 방문할 수 있지만 4는 기존에 방문했던 노드이기때문에 큐에 추가하지 않고
3만 추가해줍니다.
dequeue 과정을 반복하여 정점 4에서 방문할 수 있는 노드는 1하고 2이며 이 둘다 방문했던 노드라서 정점 3으로 넘어가줍니다.
이렇게 queue가 모두 비워지게 되면 탐색을 종료하게 됩니다.
위의 과정을 통해서 각 정점이 몇번째에 탐색을 하게 되는지를 구하면 되는 문제입니다.
문제 풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.StringTokenizer;
public class Main {
static boolean[] visited; // 방문 여부 저장 배열
static LinkedList<Integer> queue = new LinkedList<>(); // bfs queue
static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>(); // graph 저장 arraylist
static int[] turn; // 각 정점의 방문 순서 저장 배열
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int R = Integer.parseInt(st.nextToken());
visited = new boolean[N+1];
turn = new int[N+1];
for(int i=0; i<=N; i++){
graph.add(new ArrayList<>());
}
for(int i=0; i<M; i++){
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
graph.get(u).add(v);
graph.get(v).add(u);
}
for(int i=1; i<=N; i++){
Collections.sort(graph.get(i));
}
bfs(R);
for(int i=1; i<turn.length; i++){
System.out.println(turn[i]);
}
}
private static void bfs(int R){
queue.offer(R);
visited[R] = true;
int chk = 1;
while(!queue.isEmpty()){
int x = queue.poll();
turn[x] = chk++;
for(int i=0; i<graph.get(x).size(); i++){
int visit = graph.get(x).get(i);
if(!visited[visit]){
queue.offer(visit);
visited[visit] = true;
}
}
}
}
}
오늘의 회고
어제의 DFS알고리즘에 이어 BFS알고리즘 까지 알아갈 수 있어서 좋았습니다.
어제와 비슷한 방식으로 틀을 잡고 BFS알고리즘을 공부해서 적용하니 풀 수 있었습니다.
하지만 비슷한 문제들을 여러번 풀어봐야 익숙해질 것 같슴미다.... 파이팅
'TIL(Today I Learned)' 카테고리의 다른 글
[TIL] 99클럽 코테 스터디 7일차 TIL + 프로그래머스 모음사전 (0) | 2024.11.03 |
---|---|
[TIL] 99클럽 코테 스터디 6일차 TIL + 백준 2805 나무 자르기 (1) | 2024.11.02 |
[TIL] 99클럽 코테 스터디 4일차 TIL + 백준 24479 깊이 우선 탐색 1 (0) | 2024.11.01 |
[TIL] 99클럽 코테 스터디 3일차 TIL + 프로그래머스 입국심사 (java) (0) | 2024.10.30 |
[TIL] 99클럽 코테 스터디 2일차 TIL + 등차수열의 합 (1) | 2024.10.29 |