๐Ÿง ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ ( Depth First Search )

๐Ÿค” ๊นŠ์ด์šฐ์„ ํƒ์ƒ‰, DFS๋ž€?

๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰, ์ฆ‰ DFS๋Š” ๊ทธ๋ž˜ํ”„์˜ ์™„์ „ํƒ์ƒ‰(Exhaustive Search)๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜
- ๊ทธ๋ž˜ํ”„์˜ ์‹œ์ž‘๋…ธ๋“œ์—์„œ ์ถœ๋ฐœํ•ด ํƒ์ƒ‰ํ•  ํ•œ์ชฝ ๋ถ„๊ธฐ๋ฅผ ์ •ํ•œ๋‹ค.
- ์ตœ๋Œ€ ๊นŠ์ด๊นŒ์ง€ ํƒ์ƒ‰์„ ๋งˆ์น˜๋ฉด ๋‹ค๋ฅธ ๋ถ„๊ธฐ๋กœ ์ด๋™ํ•ด ๋‹ค์‹œ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

DFS๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์ด ์žˆ๋‹ค.
๊ธฐ๋Šฅ ํŠน์ง• ์‹œ๊ฐ„๋ณต์žก๋„ G(V, E)
๊ทธ๋ž˜ํ”„์˜ ์™„์ „ํƒ์ƒ‰ (Exhaustive Search)  ์žฌ๊ท€ํ•จ์ˆ˜๋‚˜ ์Šคํƒ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ๊ตฌํ˜„ O(V+E)
DFS๋Š” ์žฌ๊ท€ํ•จ์ˆ˜์˜ ์ด์šฉ์œผ๋กœ stack overflowํ˜„์ƒ์— ๋Œ€ํ•ด ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

 

๐Ÿค”  DFS๋ฅผ ์‘์šฉํ•ด ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ

- ๋ฐฑํŠธ๋ž˜ํ‚น(Backtracking) [https://www.acmicpc.net/step/34]
- ๋‹จ์ ˆ์ (Articulation Point) ์ฐพ๊ธฐ  [https://www.acmicpc.net/problem/11266]
- ๋‹จ์ ˆ์„  ์ฐพ๊ธฐ [https://www.acmicpc.net/problem/11400]
- ์‚ฌ์ดํด ์ฐพ๊ธฐ
- ์œ„์ƒ ์ •๋ ฌ(topological sort) [https://www.acmicpc.net/step/25]

 

๐Ÿค”  DFS์˜ ํ•ต์‹ฌ ์ด๋ก 

DFS๋Š” ํ•œ ๋ฒˆ ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๋ฅผ ๋‹ค์‹œ ๋ฐฉ๋ฌธํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
๋”ฐ๋ผ์„œ ๋…ธ๋“œ ๋ฐฉ๋ฌธ์—ฌ๋ถ€๋ฅผ ์ฒดํฌํ•  ๋ฆฌ์ŠคํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

DFS ํƒ์ƒ‰๋ฐฉ์‹์€ LIFOํŠน์„ฑ์˜ ์Šคํƒ์„ ์‚ฌ์šฉํ•ด ์„ค๋ช…ํ•˜์ž๋ฉด, ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

1. DFS๋ฅผ ์‹œ์ž‘ํ•  ๋…ธ๋“œ๋ฅผ ์ •ํ•œ ํ›„ ์‚ฌ์šฉํ•  ์ž๋ฃŒ๊ตฌ์กฐ ์ดˆ๊ธฐํ™” 
- DFS๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ์ดˆ๊ธฐ ์ž‘์—… ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
  โ€ฃ ์ธ์ ‘๋ฆฌ์ŠคํŠธ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ํ‘œํ˜„
  โ€ฃ ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ
  โ€ฃ ์‹œ์ž‘ ๋…ธ๋“œ ์Šคํƒ์— ์‚ฝ์ž…ํ•˜๊ธฐ
- ์Šคํƒ์— ์‹œ์ž‘๋…ธ๋“œ๋ฅผ 1๋กœ ์‚ฝ์ž…ํ•  ๋•Œ, ํ•ด๋‹น ์œ„์น˜์˜ ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฒดํฌํ•˜๋ฉด T, F, F, F, F, F ์ด๋‹ค.

 
2. ์Šคํƒ์—์„œ ๋…ธ๋“œ๋ฅผ ๊บผ๋‚ด ์ธ์ ‘ ๋…ธ๋“œ๋ฅผ ๋‹ค์‹œ ์Šคํƒ์— ์‚ฝ์ž… 
- ์ด์ œ pop์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋…ธ๋“œ๋ฅผ ๊บผ๋‚ด๊ณ  ๊บผ๋‚ธ ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰์ˆœ์„œ์— ๊ธฐ๋กํ•œ๋‹ค.
- ์ธ์ ‘๋ฆฌ์ŠคํŠธ์˜ ์ธ์ ‘๋…ธ๋“œ๋ฅผ ์Šคํƒ์— ์‚ฝ์ž…ํ•˜๋ฉฐ ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฒดํฌํ•œ๋‹ค.
- ์ด๋•Œ, ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ๋Š” T, T, T, F, F, F ์ด๋‹ค.

 

3. ์Šคํƒ์— ๊ฐ’์ด ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต 
- ์•ž์„  ๊ณผ์ •์„ ์Šคํƒ์ž๋ฃŒ๊ตฌ์กฐ์— ๊ฐ’์ด ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•˜๋ฉฐ ์ด๋ฏธ ๊ฑฐ์นœ ๋…ธ๋“œ๋Š” ์žฌ์‚ฝ์ž… ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ!

 

 

 

๐Ÿค” DFS ์ˆ˜๋„์ฝ”๋“œ

DFS์˜ ์žฌ๊ท€ ๊ตฌํ˜„

DFS๋ฅผ ์žฌ๊ท€๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜๋„ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•˜์ž๋ฉด ์ •์ ์„ ๋ฐฉ๋ฌธํ•˜๋˜ ๋ฐฉ๋ฌธ๋˜์—ˆ๋‹ค๊ณ  ํ‘œ์‹œํ•˜๊ณ  ํ•ด๋‹น ์ •์ ์˜ ์ธ์ ‘ ๊ฐ„์„ ์„ ๋ชจ๋‘ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ.
์ด๋•Œ, ํ•ด๋‹น ์ •์ ์ด ๋ฐฉ๋ฌธ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ํ•ด๋‹น ์ •์ ์— ๋Œ€ํ•ด์„œ ๋‹ค์‹œ DFS๋ฅผ callํ•˜๋Š” ํ˜•ํƒœ

์ •์ ์˜ ์ธ์ ‘ ๊ฐ„์„ ์„ ํ•˜๋‚˜์”ฉ ํƒ์ƒ‰ ํ›„ ํƒ์ƒ‰์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉด ๋น ์ ธ๋‚˜์™€ ๋‹ค๋ฅธ ์ธ์ ‘ ๊ฐ„์„ ์„ ์ด์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ํƒ์ƒ‰์ง„ํ–‰

<pseudocode>

DFS(G, v)
    visit v;
    mark v as visited;
    for all directed edges from v to w that are in G.adjacentEdges(v) do
        if vertex w is not marked as visited then
            recursively call DFS(G, w)

<python code>

 

def recursive_dfs(v, visited=[]):
    visited.append(v)
    for w in graph[v]:
        if not w in visited:
            visited = recursive_dfs(w, visited)
    return visited

์ด๋•Œ, graph๋Š” global ๋ณ€์ˆ˜๋กœ ์ž‘์šฉํ•˜๊ฒŒ ๋˜๊ณ , visited๋Š” ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๊ณ„์† ๋„ฃ์–ด์ฃผ๋Š” ํ˜•ํƒœ์ด๋‹ค.

์ด๋กœ ์ธํ•ด visited๋ฅผ ๋ฆฌํ„ดํ•ด์„œ ๊ณ„์† ๋ˆ„์ ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰์„ ํ•ด์ค˜์•ผํ•œ๋‹ค.

 

 

DFS์˜ ์Šคํƒ ๊ตฌํ˜„

์Šคํƒ์„ ์ด์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฐ˜๋ณต๋ฌธ์„ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
์Šคํƒ์„ ์ด์šฉํ•ด ๋ชจ๋“  ์ธ์ ‘ ๊ฐ„์„ ์„ ์ถ”์ถœํ•˜๊ณ  ๋‹ค์‹œ ๋„์ฐฉ์ ์ธ ์ •์ ์„ ์Šคํƒ์— ์‚ฝ์ž…ํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 

 

<pseudocode>

DFS_iterative(G,v)
    let S be a stack
    S.push(v)
    while S is not empty do
        v = S.pop()
        if v is not marked as visited then
            mark v as visited
            for all edges from v to w in G.adjacentEdges(v) do
                S.push(w)

์Šคํƒ์— ํ•œ ๋ฒˆ์— ๋ชจ๋“  ์ธ์ ‘ ๊ฐ„์„ ์˜ ์ •์ ์„ ๋‹ค pushํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž์นซ BFS๋กœ ์˜คํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค.

์—ฌ๊ธฐ์„œ ์—ผ๋‘ํ•ด์•ผํ•  ์ ์€ stack์— push๋  ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ pop์ด ๋˜๋ฉด์„œ ๋ฐฉ๋ฌธ์„ checkํ•˜๋Š” ๊ตฌ์กฐ์ด๋‹ค.

๋”ฐ๋ผ์„œ ์ •์  ๋ฐฉ๋ฌธ ์ˆœ์„œ๋กœ ๋ณธ๋‹ค๋ฉด ํ™•์‹คํžˆ DFS์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

<python code>

def iterative_dfs(start_v):
    visited = []
    stack = [start_v]
    while stack:
        v = stack.pop()
        if v not in visited:
            visited.append(v)
            for w in graph[v]:
                stack.append(w)

return visited

 

ํšจ์œจ์„ฑ

  • ์‹œ๊ฐ„ ๋ณต์žก๋„
์ธ์ ‘ ํ–‰๋ ฌ์˜ ๊ฒฝ์šฐ ํ•˜๋‚˜์˜ ์ •์  ๋‹น n๋ฒˆ check๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— O(n^2)์ด๋‹ค.
์ธ์ ‘ ๋ฆฌ์ŠคํŠธ์˜ ๊ฒฝ์šฐ ์ •์  ๋ฐฉ๋ฌธ & ํ•ด๋‹น ์ •์ ์˜ ์ธ์ ‘ ์ •์  ๋ฐฉ๋ฌธ์ด๋ฏ€๋กœ O(n+m)์ด๋‹ค.
์‹œ๊ฐ„ ๋ณต์žก๋„์˜ ๊ฒฝ์šฐ์—๋Š” ๊ฒฐ๊ตญ์—” ์–ด๋–ค ์ •์ ์„ ํƒ์ƒ‰ํ•˜๋Š๋ƒ์˜ ๋ฌธ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ณต๊ฐ„ ๋ณต์žก๋„์™€ ๋™์ผํ•˜๋‹ค.

 

  • ๊ณต๊ฐ„ ๋ณต์žก๋„
๊ณต๊ฐ„ ๋ณต์žก๋„์˜ ๊ฒฝ์šฐ, ๊ทธ๋ž˜ํ”„์™€ visited, ์Šคํƒ์„ ๋ชจ๋‘ ๊ณ ๋ คํ•ด์ฃผ์–ด์•ผ ํ•˜๊ธฐ์— ๊ทธ๋ž˜ํ”„์˜ ๊ณต๊ฐ„๋ณต์žก๋„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
์ธ์ ‘ ํ–‰๋ ฌ์˜ ๊ฒฝ์šฐ์—๋Š” ํ•˜๋‚˜์˜ ์ •์ ๊ณผ ๋ชจ๋“  ์ •์  ๊ฐ„์˜ ์—ฐ๊ฒฐ ๊ด€๊ณ„๋ฅผ ๋‹ค ํ‘œํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— O(n^2)์ด๋‹ค.
์ธ์ ‘ ๋ฆฌ์ŠคํŠธ์˜ ๊ฒฝ์šฐ์—๋Š” ๊ทธ๋ž˜ํ”„ ๋‚ด ์ •์  ๊ฐœ์ˆ˜๋ฅผ n, ๊ฐ„์„  ๊ฐœ์ˆ˜๋ฅผ m์ด๋ผ๊ณ  ํ•  ๋•Œ O(n+m)์ด๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ณต๊ฐ„๋ณต์žก๋„๋Š” ๊ทธ๋ž˜ํ”„์˜ ๊ณต๊ฐ„๋ณต์žก๋„๋ฅผ ๋”ฐ๋ผ ๊ฐ€๊ฒŒ ๋œ๋‹ค.

DFS์˜ ํšจ์œจ์„ฑ์— ๋Œ€ํ•ด ๋งํ•  ๊ฒฝ์šฐ, ์Šคํƒ๊ณผ visited๋Š” ๋ชจ๋‘ O(n)์˜ ๊ณต๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค (์ •์  ๊ฐœ์ˆ˜ n).
์ด๋Š” ๊ทธ๋ž˜ํ”„๊ฐ€ ์ธ์ ‘ ํ–‰๋ ฌ์ด๋‚˜ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋“  ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ ๋ชจ๋‘์— ํ•ด๋‹นํ•œ๋‹ค.

 

 
 
 

๐Ÿง ๋ฐฑ์ค€ 11724 (Connected Component)

- connected component ์ฆ‰, ์—ฐ๊ฒฐ์š”์†Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด์—์„œ ์„ฑ๋ฆฝํ•œ๋‹ค.

  • ์—ฐ๊ฒฐ์š”์†Œ์— ์†ํ•œ ๋ชจ๋“  ์ •์ (vertex)์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฐ„์„ (edge)๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๋˜ ๋‹ค๋ฅธ ์—ฐ๊ฒฐ์š”์†Œ์— ์†ํ•œ ์ •์ (vertex)๊ณผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฐ„์„ (edge)์ด ์žˆ์œผ๋ฉด ์•ˆ๋œ๋‹ค.

๐Ÿค”
 Algorithm ๊ณผ์ • 

0.  ๋…ธ๋“œ์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜๊ฐ€ 1000์ด๋ฏ€๋กœ ์‹œ๊ฐ„๋ณต์žก๋„ n^2์ดํ•˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
1. ๊ทธ๋ž˜ํ”„๋ฅผ ์ธ์ ‘๋ฆฌ์ŠคํŠธ๋กœ ์ €์žฅํ•œ๋‹ค. (๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์ด๊ธฐ์— ์–‘์ชฝ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ„์„ ์„ ๋ชจ๋‘ ์ €์žฅํ•œ๋‹ค.)
2. ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ชจ๋‘ False๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
3. DFS๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ, ์•„๋ž˜์™€ ๊ฐ™์ด ์ง„ํ–‰ํ•œ๋‹ค.


๐Ÿคซ  solution_11724

import sys
sys.setrecursionlimit(10000)
input = sys.stdin.readline

V, E = map(int, input().split())
CC = [[] for _ in range(V+1)]  # [[], [], [], [], [], [], []]
visit_list = [False] * (V+1)

for _ in range(E):
    u, v = map(int, input().split())
    # ์–‘๋ฐฉํ–ฅ ๊ฐ„์„ ์ด๋ฏ€๋กœ ์–‘์ชฝ์— ์ •์  ๋”ํ•˜๊ธฐ.
    CC[u].append(v)
    CC[v].append(u)
# print(CC) => [[], [2, 5], [1, 5], [4], [3, 6], [2, 1], [4]]
# ์ธ์ ‘๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ         [1]     [2]   [3]    [4]     [5]   [6]


def DFS(v):
    visit_list[v] = True
    for i in CC[v]:
        if not visit_list[i]: # ์—ฐ๊ฒฐ์š”์†Œ๊ฐ€ ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ์— F๋กœ ๋˜์–ด์žˆ์œผ๋ฉด True๋กœ ๊ณ ์น˜๊ธฐ ์œ„ํ•œ ์žฌ๊ท€
            DFS(i)

cnt = 0
for i in range(1, V+1):
    if not visit_list[i]:  # 1 2 3 4 5 6์˜ ๋ฐฉ๋ฌธ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•ด ๋ฐฉ๋ฌธํ•œ์ ์ด ์—†๋‹ค๋ฉด
        cnt += 1
        DFS(i)

print(cnt)

 

 

 

+ Recent posts