9466๋ฒ: ํ ํ๋ก์ ํธ
boj.ma
๋ฌธ์ ์์ฝ
๊ฐ๊ฐ์ ํ์์ด ๊ฐ๋ฆฌํค๋ ํ ํ์ ๋ฒํธ ์ ๋ณด๋ฅผ ํตํด ๋ฌด๋ฆฌ(cycle)๊ฐ ๋ง๋ค์ด์ง์ง ์๋ ํ์์ ์๋ฅผ ๊ตฌํ๋ค. ๊ฐ๋ น A โก๏ธ B โก๏ธ C โก๏ธ D โก๏ธ E โก๏ธ C ์์๋ก ์ง๋ช ํ๋ ๊ฒฝ์ฐ ๋ฌด๋ฆฌ๊ฐ ๋ง๋ค์ด์ง ํ์์ C, D, E์ด๊ณ , ๋ฌด๋ฆฌ๊ฐ ๋ง๋ค์ด์ง์ง ์์ ํ์์ A, B์ด๋ค. ๊ฐ๋ฆฌํค๋ ์ ๋ณด๋ฅผ ์์๋๋ก ๋ฐ๋ผ๊ฐ๊ธฐ ์ํด DFS ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ์๋ค. ๋์์ DFS ํจ์์ ๋ฐํ ๊ฐ(๊ฒฐ๊ณผ)์ ํตํด ๋ฌด๋ฆฌ ์ง์ด์ก๋์ง ์ฌ๋ถ๋ฅผ ์ ์ฅํ ์ ์๋ค.
DFS ๊ตฌ์ฑ
DFS๋ฅผ ์ด๋ป๊ฒ ๊ตฌ์ฑํ ์ ์์๊น?
์ ์ด๋ฏธ์ง ์ฒ๋ผ cycle์ด ํ์ฑ๋๋ฉด ํ์ฑ๋๋ ์๊ฐ์ ํ์์ ๋ฌด๋ฆฌ ์น๊ตฌ๋ค๋ผ๋ฆฌ ๊ฐ๋๋ค. DFS์ ๋ฐํ ๊ฐ์ผ๋ก '๋์ฐฉ' ํ์ ๋์ ํ์์ ๋ฐํํ๋ฉด ๋๋ ๊ฒ์ด๋ค. ์ดํ DFS๊ฐ ๋ฐํ(ํ๋ ํ์ดํ)๋๋ฉด์ C๋ฅผ ๊ฑฐ์น๋ ๊ฒฝ์ฐ ๊ทธ ์๊ฐ(if (๊ธฐ์กด node == ๋ฐํ๊ฐ)) -1๊ณผ ๊ฐ์ ๋น ๊ฐ์ ๋ฐํ(๋นจ๊ฐ ํ์ดํ)ํ์ฌ ๋ฌด๋ฆฌ์ ์ํ์ง ์์์ ๋ํ๋ธ๋ค.
์ฆ, ํด๋น ๋ฌธ์ ๋ DFS๋ฅผ ํตํด ์ํํ ํ ๋ฐํ ๊ฐ์ ๋ค๋ฃจ๋ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํ ์ ์๋ค.
F๊ฐ ๊ฐ์๊ธฐ B ๋๋ C๋ฅผ ๊ฐ๋ฆฌํจ๋ค๋ฉด? ๐
์ ์ฒด์ ์ธ ๋ก์ง์ ์์ ๊ฐ๊ณ , ์์ธ ์ผ์ด์ค๋ฅผ ์๊ฐํด๋ณธ๋ค. ํ์ฌ DFS๋ก ์ํํ์ง ์์ ์น๊ตฌ(F)๊ฐ ์ด๋ฏธ ์ํํ ์น๊ตฌ(A~E ์ค ํ๋)๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์๋ค. ํด๋น case์ ์น๊ตฌ F ๊ฐ์ ๊ฒฝ์ฐ ์ด๋ค ์น๊ตฌ๋ฅผ ๊ฐ๋ฆฌํค๋ -1๊ณผ ๊ฐ์ ๋น ๊ฐ์ ๋ฐํ ๋ฐ์ผ๋ฉด ๋๋ค.
์๋ํ๋ฉด 1๏ธโฃ '๋์ฐฉ'ํ ํ์์ ๋ฐํ ๊ฐ์ ๊ฐ๋ ์น๊ตฌ(C, D, E ์ค ํ๋)๋ฅผ ์ ํํ๋ ๊ฒฝ์ฐ์๋ ๋ฌด๋ฆฌ ํ์ฑ์ด ์๋ฃ๋ ๊ฒฝ์ฐ์ด๊ธฐ์ ์ด๋ค ๊ฒฝ์ฐ์๋ ์๋ก์ด ์น๊ตฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค. ๋ง์ฝ ๋ฌด๋ฆฌ์ ํฌํจ๋ ์น๊ตฌ์๋ค๋ฉด ์ด๋ฏธ DFS ์ํ์์ ํฌํจ๋์์ ๊ฒ์ด๋ค. ์ด์ -1๊ณผ ๊ฐ์ ๋น ๊ฐ์ ๋ฐ๋ ๊ฒ์ด ํ๋นํ๋ค.
2๏ธโฃ ๋น ๊ฐ์ ๋ฐํ ๋ฐ์ ํ์์ ๊ฐ๋ฆฌํค๋ ๊ฒฝ์ฐ์๋ ํด๋น ํ์์ ๋ฐ๋ผ ์ํํ๋ฉด ๊ฒฐ๊ตญ ๋น ๊ฐ์ ๋ฐ์ ํ์์ผ๋ก ๋ถํฐ ๋ค์ ๋น ๊ฐ์ ๋ฐํ ๋ฐ์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค. F โก๏ธ A์ธ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ณด๋ฉด F๋ ๋ฌด์กฐ๊ฑด A๊ฐ ๋ฐํ ๋ฐ์ ๊ฐ์ ๋ค์ ๋ฐํ ๋ฐ๋๋ค.
์ ์์ธ ์ผ์ด์ค๋ DFS ํจ์ ๋ด์ ์๋์ ๊ฐ์ด ๋ฐ์ํ ์ ์๋ค.
def dfs(node):
next_node = seq[node]
if vis[next_node] != 0:
vis_set.add(node)
vis[node] = -1
return -1
...
vis[next_node] ๊ฐ 0์ด ์๋๋ผ๋ ๊ฒ์ ์ด๋ฏธ DFS๋ฅผ ํตํด ํ ๋ฒ ์ํํ ๊ฒ์ ์ ๊ทผํ๋ ค๊ณ ํ๋ ๊ฒ์ด๋ค. ์ฆ, ์ด ๊ฒฝ์ฐ ๋ฌด์กฐ๊ฑด -1๋ก ๋ฐํ๋๋๋ก ํ๋ค.
๋ฐํ ๊ฐ์ด C์ด๋ค๊ฐ ์กฐ๊ฑด์ ๋ฐ๋ผ -1๋ก ๋ณํ๋๋ ์ฝ๋
DFS๊ฐ ๋ฐํ(ํ๋ ํ์ดํ)๋๋ฉด์ C๋ฅผ ๊ฑฐ์น๋ ๊ฒฝ์ฐ ๊ทธ ์๊ฐ(if (๊ธฐ์กด node == ๋ฐํ๊ฐ)) -1๊ณผ ๊ฐ์ ๋น ๊ฐ์ ๋ฐํ(๋นจ๊ฐ ํ์ดํ)ํ์ฌ ๋ฌด๋ฆฌ์ ์ํ์ง ์์์ ๋ํ๋ธ๋ค.
์ ์ค๋ช ๊ณผ ๊ฐ์ด ๋ฐํ ๊ฐ์ ์ด๋ป๊ฒ ๋ณํ์ํฌ ์ ์์๊น?
def dfs(node):
next_node = seq[node]
...
if vis[next_node] == 0:
vis_set.add(next_node)
root = dfs(next_node)
vis[next_node] = root
if root == next_node: return -1
return root
DFS๊ฐ ๋ฐํํ๋ ๊ฐ(root)์ด ํ์ฌ์ node(= next_node)์ ๊ฐ์ ๊ฒฝ์ฐ -1์ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ง์ ๋ฐํํ๋ ๊ฐ์ ๊ทธ๋๋ก ๋ฐํํ๋ฉด ๋๋ค.
Intuitive
๋ฐฑํธ๋ํน์์ ์์ฃผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ๋ ์ฌ๋ผ ํด๋น ๋ฌธ์ ์ ์ ์ฉ์์ผ ๋ณด์๋ค. ๋ฐฑํธ๋ํน์์๋ DFS๋ก ์ํ๋ฅผ ํ๊ณ , return ๋๋ฉด์ '์ด๋ค ์กฐ์น'๋ฅผ ์ทจํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ฌ๊ธฐ์๋ ๋ฐฑํธ๋ํน ์ฒ๋ผ '์ด๋ค ์กฐ์น'๋ฅผ ์ทจํ๊ณ ๋ค์ ๋ค์ depth๋ก ์ํํ๋ ๊ฒ์ด ์๋๋ผ, ์ํํ ๊ฒฝ๋ก๋ฅผ ๋ค์ ๋น ์ ธ๋์ค๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์๋ค.