Algorithm

Graph | DFS(๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰), BFS(๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰)

osean 2020. 10. 31. 01:55

ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ด๋ฒˆ ์ฃผ๋Š” ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋Œ€ํ‘œ์ ์ธ ๋‘ ๊ฐ€์ง€ DFS์™€ BFS์— ๊ณต๋ถ€ํ•  ์˜ˆ์ •์ด๋‹ค.
๋จผ์ € ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค์–ด์ง„ ๊ทธ๋ž˜ํ”„์˜ ๋…ธ๋“œ ๊ทธ๋ฆฌ๊ณ  ๋…ธ๋“œ์™€ ๋…ธ๋“œ ์‚ฌ์ด์— ์—ฐ๊ฒฐ๋œ ๊ฐ„์„ ์˜ ์ƒํƒœ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

๋จผ์ €, ๊ทธ๋ž˜ํ”„๋ฅผ ๋ฐ์ดํ„ฐ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ € ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ์ธ์ ‘ ํ–‰๋ ฌ ๋˜๋Š” ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

Graph

 

[์ž๋ฃŒ๊ตฌ์กฐ] ๊ทธ๋ž˜ํ”„(Graph)๋ž€ - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

์ธ์ ‘ ํ–‰๋ ฌ

์ธ์ ‘ ํ–‰๋ ฌ์ด๋ž€ ๊ทธ๋ž˜ํ”„์˜ ์—ฐ๊ฒฐ ๊ด€๊ณ„๋ฅผ 2์ฐจ์› ๋ฐฐ์—ด๋กœ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ์‹์„ ๋งํ•œ๋‹ค.
์ฆ‰, ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๋Š” ์ด๋ฏธ ์ •ํ•ด์ ธ ์žˆ์œผ๋‹ˆ ๊ฐ ๋…ธ๋“œ(x์ถ• index ๋ฒˆํ˜ธ)์™€ ๋…ธ๋“œ(y์ถ• index ๋ฒˆํ˜ธ) ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ๋ฐ์ดํ„ฐ๋กœ ์ €์žฅํ•ด ํ…Œ์ด๋ธ”๋กœ ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ธ์ ‘ ํ–‰๋ ฌ์€ ๊ฐ๊ฐ์˜ ๋…ธ๋“œ ๊ฐ„ ๊ด€๊ณ„๋ฅผ(๋…ผ๋ฆฌ ํ˜น์€ 0,1) ํŒŒ์•…ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— O(1)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค.(n ~ m๊นŒ์ง€ ๋ชจ๋“  ๋ฐฐ์—ด์˜ ๋ฐฉ์˜ ๊ด€๊ณ„๋ฅผ ํŒŒ์•…ํ•œ๋‹ค.)

 

ํ•˜์ง€๋งŒ V๊ฐœ์˜ ๋…ธ๋“œ์™€ E๊ฐœ์˜ ๊ฐ„์„ ์ด ์กด์žฌํ•  ๋•Œ E๊ฐœ์˜ ๊ฐ„์„ ์„ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” n ~ V๊นŒ์ง€ ๋ฐฐ์—ด์˜ ๋ฐฉ์„ ํŒŒ์•…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” O(V) ๋งŒํผ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค. ์ฆ‰, ๋ถˆํ•„์š”ํ•œ ์‹œ๊ฐ„๊ณผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์†Œ๋ชจํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋ž€ ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒํ˜•์„ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฉฐ ์ธ์ ‘ ํ–‰๋ ฌ์ด V๊ฐœ์˜ ๋…ธ๋“œ์—์„œ E๊ฐœ์˜ ๊ฐ„์„ ์„ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด O(V)๋งŒํผ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๋Š” ๋‹จ์ ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ์•ˆ๋œ ๋ฐฉ๋ฒ•์ด๋‹ค.
์ด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ ๋ฆฌ์ŠคํŠธ์˜ index๋ฅผ ๋…ธ๋“œ๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ํ•ด๋‹น ๋…ธ๋“œ์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” ๋…ธ๋“œ์˜ ๋ฒˆํ˜ธ๋ฅผ ์ €์žฅํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ์ธ๋ฑ์Šค์˜ ๊ธธ์ด๋Š” ํ•ด๋‹น ๋…ธ๋“œ์— ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ์— ๋Œ€ํ•œ ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜๋ผ๋Š” ๋œป์ด๋‹ค.

 

ํŒŒ์ด์ฌ์˜ ๊ฒฝ์šฐ ์ž์ฒด์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒํ˜•์„ ์ด์šฉํ•ด append() ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, C๋‚˜ JAVA์™€ ๊ฐ™์€ ์–ธ์–ด๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” List ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

DFS - ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰

 

[์•Œ๊ณ ๋ฆฌ์ฆ˜] ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰(DFS)์ด๋ž€ - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

DFS(Depth First Search), ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์ด๋ž€ ํ˜„์žฌ์˜ ๋…ธ๋“œ(ํ˜น์€ ๋ฃจํŠธ ๋…ธ๋“œ)์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ๋“ค์„ ํŠน์ •ํ•œ ๊ธฐ์ค€(ex.๋…ธ๋“œ์˜ ๋ฒˆํ˜ธ๊ฐ€ ์ž‘์€ ์ˆœ์„œ๋Œ€๋กœ)์œผ๋กœ ์ธ์ ‘ํ•œ ๋…ธ๋“œ์˜ ์ œ์ผ ๊นŠ์€ ๊ณณ๊นŒ์ง€ ํƒ์ƒ‰ํ•˜๋ฉฐ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— DFS๋Š” Stack ์ž๋ฃŒ ๊ตฌ์กฐ๋‚˜ ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ณดํ†ต์€ ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

  • Python - ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ
# DFS ๋ฉ”์„œ๋“œ ์ •์˜
def dfs(graph, v, visited):
    # JAVA : stack.push()
    # Python : stack.append()

    # ํ˜„์žฌ์˜ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ
    visited[v] = True
    print(v, end=' ')

    # ํ˜„์žฌ ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐ๋œ ๋‹ค๋ฅธ ๋…ธ๋“œ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ๋ฐฉ๋ฌธ
    for i in graph[v]:
        if not visited[i]:
            dfs(graph, i, visited)


graph = [
    [],
    [2, 3, 8],
    [1, 7],
    [1, 4, 5],
    [3, 5],
    [3, 4],
    [7],
    [2, 6, 8],
    [1, 7]
]

visited = [False] * 9

dfs(graph, 1, visited)
  • JAVA - DFS๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐ ์ฝ”๋“œ
package ์‹ฌ์„ฑํ—Œ.์•Œ๊ณ ๋ฆฌ์ฆ˜_4์ฃผ์ฐจ;

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

public class ๋ฐ”์ด๋Ÿฌ์Šค_2606 {

	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static int n;
	static int m;
	static int count;
	static boolean[][] graph;
	static boolean[] visited;

	public static void dfs(int index) {
		visited[index] = true;

		for (int i = 1; i <= n; i++) {
			if (graph[index][i] == true && visited[i] == false) {
				count++;
				dfs(i);
			}
		}
	}

	public static void main(String[] args) throws IOException {
		n = Integer.parseInt(br.readLine());
		m = Integer.parseInt(br.readLine());

		graph = new boolean[n + 1][n + 1];
		visited = new boolean[n + 1];

		for (int i = 1; i <= m; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());

			graph[x][y] = true;
			graph[y][x] = true;
		}
		dfs(1);
		System.out.println(count);
	}
}

๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ๋…ธ๋“œ ๊ฐ„ ๊ฐ„์„ ์„ ์กฐํšŒํ•œ๋‹ค.
๋”ฐ๋ผ์„œ,

  • ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ
    • O(N + E)
  • ์ธ์ ‘ ํ–‰๋ ฌ
    • O(N^2)

์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ „์ฒด๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์€ ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰๋ณด๋‹ค ๋Š๋ฆฌ๋‹ค.

BFS - ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰

 

[์•Œ๊ณ ๋ฆฌ์ฆ˜] ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰(BFS)์ด๋ž€ - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

BFS(Breadth First Search), ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์ด๋ž€ ํ˜„์žฌ์˜ ๋…ธ๋“œ(ํ˜น์€ ๋ฃจํŠธ ๋…ธ๋“œ)์˜ ์ธ์ ‘ํ•œ ๋…ธ๋“œ๋ฅผ ๋จผ์ € ํƒ์ƒ‰ํ•˜๊ณ , ์ธ์ ‘ํ•œ ๋…ธ๋“œ๋ฅผ ํŠน์ • ๊ธฐ์ค€์˜ ์ˆœ์„œ๋Œ€๋กœ ๋‹ค์‹œ ์ธ์ ‘ ๋…ธ๋“œ์˜ ์ธ์ ‘ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ์‹์„ ์˜๋ฏธํ•œ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— BFS๋Š” Queue ์ž๋ฃŒ ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•œ๋‹ค.
๋”ฐ๋ผ์„œ, ์žฌ๊ท€์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ํ•ด๋‹น ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•  ๋•Œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ์— ๋Œ€ํ•ด ๋ฐฉ๋ฌธ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•ด์•ผ ๋‹ค์Œ ๋…ธ๋“œ์˜ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

  • Python - deque ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„
# BFS ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์€ ํ์™€ ๋‹ค์ค‘ ๋ฐ˜๋ณต๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

from collections import deque

def bfs_function(graph, start, visited):
    # ํ ๊ตฌํ˜„์„ ์œ„ํ•ด deque ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
    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

graph = [
    [],
    [2, 3, 8],
    [1, 7],
    [1, 4, 5],
    [3, 5],
    [3, 4],
    [7],
    [2, 6, 8],
    [1, 7]
]

visited = [False] * 9

bfs_function(graph, 1, visited)
  • JAVA - ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ Queue ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„
package ์‹ฌ์„ฑํ—Œ.์•Œ๊ณ ๋ฆฌ์ฆ˜_4์ฃผ์ฐจ;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

public class BFS_๋„ˆ๋น„์šฐ์„ ํƒ์ƒ‰ {

	static Queue<Integer> queue = new LinkedList<Integer>();

	public static void dfs(int[][] graph, int start, boolean[] visited) {
		queue.offer(start);
		visited[start] = true;

		while (queue.size() != 0) {
			int save = queue.poll();
			System.out.print(save + " ");
			for (int i = 0; i < graph[save].length; i++) {
				if (!visited[graph[save][i]]) {
					queue.offer(graph[save][i]);
					visited[graph[save][i]] = true;
				}
			}
		}
	}

	public static void main(String[] args) throws NumberFormatException, IOException {

		int[][] graph = { {}, { 2, 3, 8 }, { 1, 7 }, { 1, 4, 5 }, { 3, 5 }, { 3, 4 }, { 7 }, { 2, 6, 8 }, { 1, 7 } };
		boolean[] visited = new boolean[graph.length + 1];
		for (int i = 1; i < visited.length; i++) {
			visited[i] = false;
		}
		dfs(graph, 1, visited);
	}

}

๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰๋Š”

  • ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ
    • O(N + E)
  • ์ธ์ ‘ ํ–‰๋ ฌ
    • O(N^2)

์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค.

์ฐธ๊ณ ํ•˜๋ฉด ์ข‹์€ ์˜์ƒ