
문제
그래프를 DFS로 탐색한 결과와 BFS로 탐색한 결과를 출력하는 프로그램을 작성하시오. 단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문하고, 더 이상 방문할 수 있는 점이 없는 경우 종료한다. 정점 번호는 1번부터 N번까지이다.
입력
첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 양방향이다.
출력
첫째 줄에 DFS를 수행한 결과를, 그다음 줄에는 BFS를 수행한 결과를 출력한다. V부터 방문된 점을 순서대로 출력하면 된다.

문제 접근 방법
이번 문제는 너비 우선 탐색(BFS : Breath First Search)과 깊이 우선 탐색(DFS : Depth First Search) 함수를 구현할 수 있는가를 묻는 문제이다. 따라서 단순히 그냥 두 함수를 구현해주면 된다.
너비 우선 탐색 (BFS)
1. 탐색을 시작할 정점을 큐(Queue)에 저장해준다.
2. 시작할 정점을 방문했다고 표시한다.
3. 큐가 Empty큐가 될 때까지 다음 과정을 반복해준다.
3-1. 큐에서 deQueue 하여 다음 방문할 정점을 결정한다.
3-2. 방문한 정점에 부속된 노드가 연결하는 다른 정점을 큐에 enQueue 한다.
(이전에 방문했던 정점이면 enQueue하지 않는다.)
3-3. enQueue해준 노드로 연결된 반대 노드를 방문했다고 표시해준다.
깊이 우선 탐색 (DFS)
1. 탐색을 시작할 정점을 스택(Stack)에 저장해준다.
2. 스택이 Empty스택이 될 때까지 다음 과정을 반복해준다.
2-1. 스택에서 pop 하여 다음 방문할 정점을 결정한다.
2-2. 스택에서 pop 한 정점이 이미 방문한 정점인지 확인한다.
2-2-1. 이전에 방문했던 정점이면 continue;
2-2-2. 이전에 방문하지 않았던 정점이면 계속해서 실행한다.
2-3. 방문한 정점을 방문했다고 표시한다.
2-4. 방문한 정점에 부속된 노드가 연결하는 다른 정점을 스택에 push 한다.
(이전에 방문했던 정점이면 push하지 않는다.)
JAVA 코드 풀이
import java.util.*; | |
import java.io.*; | |
public class Main { | |
static int n; | |
public static void main(String args[]) throws IOException{ | |
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | |
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); | |
StringTokenizer init = new StringTokenizer(br.readLine()); | |
n = Integer.parseInt(init.nextToken()); | |
int m = Integer.parseInt(init.nextToken()); | |
int sV = Integer.parseInt(init.nextToken()); | |
boolean node[][] = new boolean[n+1][n+1]; | |
int v1, v2; | |
while(m-- > 0) { | |
StringTokenizer st = new StringTokenizer(br.readLine()); | |
v1 = Integer.parseInt(st.nextToken()); | |
v2 = Integer.parseInt(st.nextToken()); | |
node[v1][v2] = true; | |
node[v2][v1] = true; | |
} | |
bw.write(dfs(sV, node)+"\n"); | |
bw.write(bfs(sV, node)); | |
bw.close(); | |
} | |
static String bfs(int v, boolean node[][]) { // 너비 우선 탐색 | |
StringBuilder sb = new StringBuilder(); // 경로 저장할 변수 | |
Queue<Integer> queue = new LinkedList<>(); | |
boolean visited[] = new boolean[n+1]; // 방문 여부 표시 배열 | |
queue.add(v); // 시작 정점 저장 | |
visited[v] = true; // 정점 방문 표시 | |
int idx; | |
while(!queue.isEmpty()) { | |
idx = queue.remove(); | |
sb.append(idx+" "); // 경로 저장 | |
for(int i=1; i<node.length; i++) | |
if(node[idx][i] && !visited[i]) { // idx정점과 i정점 사이에 간선이 존재하는 경우 && i정점을 방문하지 않은 경우 | |
queue.add(i); // 다음 방문 예정 정점 저장 | |
visited[i] = true; // 다음 방문 예정이므로 미리 i정점 방문 표시 | |
} | |
} | |
return sb.toString(); | |
} | |
static String dfs(int v, boolean node[][]) { // 깊이 우선 탐색 | |
StringBuilder sb = new StringBuilder(); // 경로 저장할 변수 | |
Stack<Integer> stack = new Stack<>(); | |
boolean visited[] = new boolean[n+1]; // 방문 여부 표시 배열 | |
stack.add(v); // 시작 정점v 저장 | |
int idx; | |
while(!stack.isEmpty()) { | |
idx = stack.pop(); | |
if(visited[idx]) // 이미 방문했던 정점이면 다음 정점 방문 | |
continue; | |
visited[idx] = true; // idx정점 방문 표시 | |
sb.append(idx+" "); // 경로 저장 | |
for(int i=n; i>0; i--) | |
if(node[idx][i] && !visited[i]) // idx정점과 i정점 사이에 간선이 존재하는 경우 && i정점을 방문하지 않은 경우 | |
stack.add(i); // 다음 방문 예정 정점 저장 | |
} | |
return sb.toString(); | |
} | |
} |
코드 실행 결과

후기
이번 문제는 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
'문제 풀이 > [JAVA_자바] 백준' 카테고리의 다른 글
[JAVA / 자바] 백준 1003번 - 피보나치 함수 (0) | 2022.02.02 |
---|---|
[JAVA / 자바] 백준 1654번 - 랜선 자르기 (0) | 2022.02.01 |
[JAVA / 자바] 백준 1463번 - 1로 만들기 (0) | 2022.01.28 |
[JAVA / 자바] 백준 10989번 - 수 정렬하기 3 (0) | 2022.01.27 |
[JAVA / 자바] 백준 2805번 - 나무 자르기 (0) | 2022.01.26 |