본문 바로가기
CS/알고리즘

BFS - 너비 우선 탐색 / DFS - 깊이 우선 탐색

by lms0806 2023. 1. 22.
728x90
반응형

너비 우선 탐색(Breadth First Search) / DFS(Depth First Search)은 시작지점부터 갈 수 있는 지점들을 들리면서, 더이상 갈 곳이 없을때까지 반복한 후 종료한다.

 

ex)

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

 

2606번: 바이러스

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어

www.acmicpc.net

해당 문제는 이런 모양의 간선과 노드들로 이루어져 있습니다.

1번 컴퓨터에 바이러스가 걸리게 된다면, 1과 2, 3, 5, 6 총 4개의 컴퓨터가 1번 컴퓨터에 의해 바이러스에 감염되면서, 5개의 컴퓨터가 바이러스에 걸리게 됩니다.

 

해당 문제는 BFS / DFS(인접행렬, 인접리스트)로 풀 수 있습니다. 왠만해서는 DFS로 풀시, 인접리스트를 추천드립니다.

<인접 리스트 BFS>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	static ArrayList<Integer>[] arr;
	static boolean[] visited;
	static int n, answer = 0;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
		
		n = Integer.parseInt(br.readLine()) + 1;
		int m = Integer.parseInt(br.readLine());
		
		arr = new ArrayList[n]; // 인접 리스트
		visited = new boolean[n]; //방문 체크
		
		for(int i = 1; i < n; i++) {
			arr[i] = new ArrayList<>();
		}
		
		while(m --> 0) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken()), b = Integer.parseInt(st.nextToken());
			
			arr[a].add(b);
			arr[b].add(a);
		}
		
		dfs(1); // 1번 컴퓨터 부터 시작
		
		System.out.print(answer - 1); // 1번 컴퓨터를 제외한 감염된 컴퓨터 개수
	}
	
	public static void dfs(int start) {
		Queue<Integer> queue = new LinkedList<>();
		boolean[] visited = new boolean[n];
		visited[start] = true;
		queue.add(start);
		
		while(!queue.isEmpty()) {
			int now = queue.poll();
			
			answer++;
			
			for(int i = 0; i < arr[now].size(); i++) {
				int next = arr[now].get(i);
				
				if(!visited[next]) {
					visited[next] = true;
					queue.add(next);
				}
			}
		}
	}
}

<인접 행렬 DFS> 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	static int[][] arr;
	static boolean[] visited;
	static int answer = 0;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
		
		int n = Integer.parseInt(br.readLine()) + 1, m = Integer.parseInt(br.readLine());
		
		arr = new int[n][n]; // 인접 행렬
		visited = new boolean[n]; //방문 체크
		
		while(m --> 0) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken()), b = Integer.parseInt(st.nextToken());
			
			arr[a][b] = 1;
			arr[b][a] = 1;
		}
		
		dfs(1); // 1번 컴퓨터 부터 시작
		
		System.out.print(answer - 1); // 1번 컴퓨터를 제외한 감염된 컴퓨터 개수
	}
	
	public static void dfs(int start) {
		if(start == arr.length) {
			return;
		} // 마지막 컴퓨터까지 확인 했으면 종료
		
		visited[start] = true;
		answer++;
		
		for(int i = 0; i < arr.length; i++) {
			if(arr[start][i] == 1 && !visited[i]) {
				dfs(i);
			} // 감염된 컴퓨터와 연결되어 있으면 전염
		}
	}
}

<인접 리스트 DFS>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
	static ArrayList<Integer>[] arr;
	static boolean[] visited;
	static int answer = 0;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
		
		int n = Integer.parseInt(br.readLine()) + 1, m = Integer.parseInt(br.readLine());
		
		arr = new ArrayList[n]; // 인접 리스트
		visited = new boolean[n]; //방문 체크
		
		for(int i = 1; i < n; i++) {
			arr[i] = new ArrayList<>();
		}
		
		while(m --> 0) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken()), b = Integer.parseInt(st.nextToken());
			
			arr[a].add(b);
			arr[b].add(a);
		}
		
		dfs(1); // 1번 컴퓨터 부터 시작
		
		System.out.print(answer - 1); // 1번 컴퓨터를 제외한 감염된 컴퓨터 개수
	}
	
	public static void dfs(int start) {
		if(start == arr.length) {
			return;
		} // 마지막 컴퓨터까지 확인 했으면 종료
		
		visited[start] = true;
		answer++;
		
		for(int i = 0; i < arr[start].size(); i++) {
			if(!visited[arr[start].get(i)]) {
				dfs(arr[start].get(i));
			} // 감염된 컴퓨터와 연결되어 있으면 전염
		}
	}
}

 

 

 

※ BFS 관련 문제 추천

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

 

4963번: 섬의 개수

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다. 둘째 줄부터 h개 줄에는 지도

www.acmicpc.net

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

 

2667번: 단지번호붙이기

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

www.acmicpc.net

 

 

728x90
반응형

댓글