문제 풀이/[JAVA_자바] 백준

[JAVA / 자바] 백준 1260번 - DFS와 BFS

Seunghyun_KO 2022. 1. 31. 09:00
728x90
반응형

문제

그래프를 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();
}
}
view raw 1260.java hosted with ❤ by GitHub

코드 실행 결과


후기

이번 문제는 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

728x90
반응형