DOing
[์๊ณ ๋ฆฌ์ฆ] Disjoint Sets(์๋ก์ ์งํฉ) ๋ณธ๋ฌธ
๐ก Disjoint Sets(์๋ก์ ์งํฉ)?
์๋ก์ ์งํฉ์ด๋, ๊ณตํต ์์๊ฐ ์๋ ๋์งํฉ์ ์๋ฏธํ๋ค. ์ผ์ชฝ ๊ทธ๋ฆผ์์ ์งํฉ A์ B๋ ์๋ก์ ๊ด๊ณ์ด๊ณ , ์ค๋ฅธ์ชฝ ๊ทธ๋ฆผ์์ ์งํฉ A์ B๋ ์๋ก์ ๊ด๊ณ๊ฐ ์๋๋ค.
์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ๋ ์๋ก์ ๋ถ๋ถ ์งํฉ๋ค๋ก ๋๋์ด์ง ์์๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์๋ฃ๊ตฌ์กฐ์ด๋ค. ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ๋ union-find ์๋ฃ๊ตฌ์กฐ๋ผ๊ณ ๋ ๋ถ๋ฆฐ๋ค. ์ฌ์ฉ๋๋ ์ฐ์ฐ์ ์ด๋ฆ ์์ฒด๊ฐ union๊ณผ find์ด๊ธฐ๋ ํ๊ณ , ๋ ์งํฉ์ด ์๋ก์ ๊ด๊ณ์ธ์ง ํ์ธํ ์ ์๋ค๋ ๋ง์ ๊ฐ ์งํฉ์ด ์ด๋ค ์์๋ฅผ ๊ณตํต์ผ๋ก ๊ฐ์ง๊ณ ์๋์ง๋ฅผ ํ์ธํ ์ ์๋ค๋ ๋ง๊ณผ ๊ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
๐ก Disjoint Sets ๋์ ๊ณผ์
Disjoint Sets ๋ฅผ ๊ตฌํํ ๋๋ ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ด์ฉํ์ฌ ์งํฉ์ ํํํ๋ค. ํธ๋ฆฌ๋ก ๋ถ๋ถ์งํฉ์ ํํํ๊ณ find๋ฅผ ํตํด ๋ฃจํธ ๋ ธ๋๋ฅผ ์ฐพ๊ณ union์ผ๋ก ํธ๋ฆฌ๋ฅผ ํฉ์น๋ค. ์๋ก์ ์งํฉ ๊ณ์ฐ ์๊ณ ๋ฆฌ์ฆ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. union(ํฉ์งํฉ)์ฐ์ฐ์ ํ์ธํ์ฌ, ์๋ก ์ฐ๊ฒฐ๋ ๋ ๋ ธ๋ A, B๋ฅผ ํ์ธํ๋ค.
1) A์ B์ ๋ฃจํธ๋ ธ๋ A'์ B'๋ฅผ ๊ฐ๊ฐ ์ฐพ๋๋ค.
2) A'๋ฅผ B'์ ๋ถ๋ชจ๋ ธ๋๋ก ์ค์ ํ๋ค.(=B'๊ฐ A'๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ๋ค.)
* ๋ณดํต A'์ B'์ค์์ ๋ ๋ฒํธ ์์ ์์๊ฐ ๋ถ๋ชจ ๋ ธ๋๊ฐ ๋๋๋ก ๊ตฌํํ๋ค.
2. ๋ชจ๋ union(ํฉ์งํฉ) ์ฐ์ฐ์ ์ฒ๋ฆฌํ ๋๊น์ง 1๋ฒ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
์์๋ก ๋ค์๊ณผ ๊ฐ์ union์ฐ์ฐ์ ์ฃผ์ด์ก์ ๋ ๋์๊ณผ์ ์ ์ดํด๋ณด๊ฒ ๋ค.
union(1, 4) union(2, 3) union(2, 4) union(5, 6)
[ ์ด๊ธฐ ๋จ๊ณ ]
์ด๊ธฐ ๋จ๊ณ์์๋ ์๊ธฐ์์ ์ ๋ฃจํธ๋ ธ๋๋ก ๊ฐ์ง๊ณ ์๋ค.
์ ์ํ ์ ์ ์ฌ๊ธฐ์์ ๋ถ๋ชจ ํ ์ด๋ธ์ ๋ถ๋ชจ์ ๋ํ ์ ๋ณด๋ง์ ๋ด๊ณ ์๋ค. ๋ค์ ๋งํด ํน์ ๋ ธ๋์ ๋ฃจํธ๋ฅผ ํ์ธํ๊ณ ์ ํ ๋๋ ์ฌ๊ท์ ์ผ๋ก ๋ถ๋ชจ๋ฅผ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ์ ์ต์ข ์ ์ธ ๋ฃจํธ ๋ ธ๋๋ฅผ ์ฐพ์์ผํ๋ค.
[ step1 ]
1) 1์ ๋ฃจํธ ๋ ธ๋๋ 1์ด๊ณ , 4์ ๋ฃจํธ๋ ธ๋๋ 4์ด๋ค.
2) ๋ ์์ ๋ฃจํธ๋ ธ๋์ธ 1์ ๋ฃจํธ๋ ธ๋ 4์ ๋ถ๋ชจ๋ก ์ค์ ํ๋ค.
[ step2 ]
1) 2์ ๋ฃจํธ๋ ธ๋๋ 2์ด๊ณ , 3์ ๋ฃจํธ๋ ธ๋๋ 3์ด๋ค.
2) ๋ ์์ ๋ฃจํธ๋ ธํธ์ธ 2์ ๋ฃจํธ๋ ธ๋ 3์ ๋ถ๋ชจ๋ก ์ค์ ํ๋ค.
[ step3 ]
1) 2์ ๋ฃจํธ๋ ธ๋๋ 2์ด๊ณ , 4์ ๋ฃจํธ๋ ธ๋๋ 1์ด๋ค.
2) ๋ ์์ ๋ฃจํธ๋ ธ๋์ธ 1์ ๋ฃจํธ๋ ธ๋ 2์ ๋ถ๋ชจ๋ก ์ค์ ํ๋ค.
[ step4 ]
1) 5์ ๋ฃจํธ๋ ธ๋๋ 5์ด๊ณ , 6์ ๋ฃจํธ๋ ธ๋๋ 6์ด๋ค.
2) ๋ ์์ ๋ฃจํธ๋ ธ๋์ธ 5๋ฅผ ๋ฃจํธ๋ ธ๋ 6์ ๋ถ๋ชจ๋ก ์ค์ ํ๋ค.
๐ก Disjoint Sets ๊ตฌํ
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ์ํด์ ๋ฃจํธ๋
ธ๋๋ฅผ ๋ฐํํ๋ find์ฐ์ฐ
def find_parent(parent, x):
# ๋ฃจํธ๋
ธ๋๊ฐ ์๋๋ผ๋ฉด, ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท์ ์ผ๋ก ํธ์ถ
if parent[x] != x:
return find_parent(parent, parent[x])
# ์์ ์ด ๋ฃจํธ๋
ธ๋์ผ๋
return x
# ๋ ์์๊ฐ ์ํ ์งํฉ์ ํฉ์น๋ union์ฐ์ฐ
def union_parent(parent, a, b):
a = find_parent(parent, a)
b = find_parent(parent, b)
if a < b:
parent[b] = a
else:
parent[a] = b
# ๋
ธ๋์ ๊ฐ์์ ๊ฐ์ (union ์ฐ์ฐ)์ ๊ฐ์ ์
๋ ฅ๋ฐ๊ธฐ
v, e = map(int, input().split())
# ๋ถ๋ชจํ
์ด๋ธ
parent = [i for i in range(v+1)] # ์ด๊ธฐ ์ํ์์ ๋ชจ๋ ๋
ธ๋์ ๋ฃจํธ๋
ธ๋๋ ์๊ธฐ์์
# union ์ฐ์ฐ์ ๊ฐ๊ฐ ์ํ
for i in range(e):
a,b = map(int, input().split())
union_parent(parent, a, b)
# ๊ฐ ์์์ ๋ฃจํธ๋
ธ๋๋ฅผ ์ถ๋ ฅ
print("๊ฐ ์์์ ๋ฃจํธ๋
ธ๋:", end=' ')
for i in range(1, v+1):
print(find_parent(parent, i), end=' ')
print()
# ๋ถ๋ชจํ
์ด๋ธ ๋ด์ฉ ์ถ๋ ฅ
print("๋ถ๋ชจํ
์ด๋ธ:", end=' ')
for i in range(1, v+1):
print(parent[i], end=' ')
์ ๋ ฅ | ์ถ๋ ฅ |
6 4 1 4 2 3 2 4 5 6 |
๊ฐ ์์์ ๋ฃจํธ๋
ธ๋: 1 1 1 1 5 5 ๋ถ๋ชจํ ์ด๋ธ: 1 1 2 1 5 5 |
๐ก ๊ฒฝ๋ก ์์ถ ๊ธฐ๋ฒ
์์ ์ฝ๋๋ก ๊ตฌํ์์ ๋ต์ ๊ตฌํ ์๋ ์์ง๋ง, findํจ์๊ฐ ๋นํจ์จ์ ์ผ๋ก ๋์ํ๋ค๋ ๋ฌธ์ ์ ์ด ์๋ค. ๋ฃจํธ ๋ ธ๋๋ฅผ ์ฐพ๊ธฐ์ํด์ ๋ถ๋ชจ ํ ์ด๋ธ์ ๊ณ์ํด์ ํ์ธํ๋ฉฐ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ์ผํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ต์ ์ ๊ฒฝ์ฐ findํจ์๊ฐ ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ค ํ์ธํ๋ ํฐ๋ผ ์๊ฐ๋ณต์ก๋๊ฐ O(V)์ด๋ค.
์ด๋ฌํ findํจ์๋ฅผ ๊ฒฝ๋ก ์์ถ ๊ธฐ๋ฒ(Path Compression)์ ์ฌ์ฉํ๋ฉด ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ ํ ์ ์๋ค. ๋ถ๋ชจ ํ ์ด๋ธ์ ๋ฃจํธ๋ ธ๋๋ฅผ ๋ฐ๋ก ์ ์ฅํ๋ ๊ฒ์ด๋ค. ๊ฒฝ๋ก ์์ถ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋ฃจํธ๋ ธ๋์ ๋์ฑ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๋ค. ์์ ์์๋ค๊ณผ ๋์ผํ ์ํฉ์ ๋ํด์ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ์ด ๋๋ค.
์ฝ๋๋ก ๊ตฌํํ๊ฒ ๋๋ฉด ๋๋จธ์ง๋ ๋ชจ๋ ๋์ผํ๊ณ find_parent()๋ง ์์ ๋๋ค.
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ์ํด์ ๋ฃจํธ๋
ธ๋๋ฅผ ๋ฐํํ๋ find์ฐ์ฐ
def find_parent(parent, x):
# ๋ฃจํธ๋
ธ๋๊ฐ ์๋๋ผ๋ฉด, ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท์ ์ผ๋ก ํธ์ถ
if parent[x] != x:
parent[x] = find_parent(parent, parent[x]) # ๋ถ๋ชจ๋ฅผ ๋ฃจํธ๋
ธ๋๋ก ๋ณ๊ฒฝ
return parent[x]
์ ๋ ฅ | ์ถ๋ ฅ |
6 4 1 4 2 3 2 4 5 6 |
๊ฐ ์์์ ๋ฃจํธ๋
ธ๋: 1 1 1 1 5 5 ๋ถ๋ชจํ ์ด๋ธ: 1 1 1 1 5 5 |
๐ก ์ฌ์ดํด ํ๋ณ ์๊ณ ๋ฆฌ์ฆ
Disjoint Sets๋ ๋ค์ํ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉ๋ ์ ์๋ค. ํนํ ๋ฌด๋ฐฉํฅ ๊ทธ๋ํ ๋ด์์์ ์ฌ์ดํด์ ํ๋ณํ ๋ ์ฌ์ฉ๋ ์ ์๋ค. ์ฐธ๊ณ ๋ก ๋ฐฉํฅ๊ทธ๋ํ์์์ ์ฌ์ดํด ์ฌ๋ถ๋ DFS๋ฅผ ์ด์ฉํด ํ๋ณํ ์ ์๋ค.
[ ๋์ ๊ณผ์ ]
1. ๊ฐ ๊ฐ์ ์ ํ์ธํ๋ฉฐ ๋ ๋ ธ๋์ ๋ฃจํธ๋ ธ๋๋ฅผ ํ์ธํ๋ค.
2. ๋ฃจํธ๋ ธ๋๊ฐ ์๋ก ๋ค๋ฅด๋ค๋ฉด ๋ ๋ ธ๋์ ๋ํ์ฌ union์ฐ์ฐ์ ์ํํ๋ค.
3. ๋ฃจํธ๋ ธ๋๊ฐ ์๋ก ๊ฐ๋ค๋ฉด ์ฌ์ดํด์ด ๋ฐ์ํ ๊ฒ์ด๋ค.
4. ๊ทธ๋ํ์ ํฌํจ๋์ด์๋ ๋ชจ๋ ๊ฐ์ ์ ๋ํ์ฌ 1~3๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
๋ง์ฝ ๋ชจ๋ ๊ฐ์ ์ด ์ฒ๋ฆฌ๋ ๋๊น์ง ์ฌ์ดํด์ด ๋ฐ์ํ์ง ์์๋ค๋ฉด ํด๋น ๊ทธ๋ํ์์๋ ์ฌ์ดํด์ด ์๋ค๋ผ๊ณ ํ๋จ๋ ์ ์๋ค.
[ step0 ]
[ step 1 ]
1. 1์ ๋ฃจํธ๋ ธ๋๋ 1, 2์ ๋ฃจํธ๋ ธ๋๋ 2์ด๋ค.
2. ๋ฃจํธ๋ ธ๋๊ฐ ์๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋ ธ๋์ ๋ํด union์ฐ์ฐ์ ์ํํ๋ค.
[ step 2 ]
1. 1์ ๋ฃจํธ๋ ธ๋๋ 1์ด๊ณ 3์ ๋ฃจํธ๋ ธ๋๋ 3์ด๋ค.
2. ๋ฃจํธ๋ ธ๋๊ฐ ์๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋ ธ๋์ ๋ํด union์ฐ์ฐ์ ์ํํ๋ค.
[ step 3 ]
1. 2์ ๋ฃจํธ๋ ธ๋๋ 1์ด๊ณ 3์ ๋ฃจํธ๋ ธ๋๋ 1์ด๋ค.
2. ๋ฃจํธ๋ ธ๋๊ฐ ์๋ก ๊ฐ๋ค. ๋ ๋ ธ๋๊ฐ ์ด๋ฏธ ๊ฐ์ ๋ ธ๋์ ์ํด ์๋ค๋ ๋ป์ด๊ณ ํด๋น ๊ทธ๋ํ์ ์ฌ์ดํด์ด ์๋ค๋ ์๋ฏธ์ด๋ค.
๐ก ์ฌ์ดํด ํ๋ณ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ์ํด์ ๋ฃจํธ๋
ธ๋๋ฅผ ๋ฐํํ๋ find์ฐ์ฐ
def find_parent(parent, x):
# ๋ฃจํธ๋
ธ๋๊ฐ ์๋๋ผ๋ฉด, ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท์ ์ผ๋ก ํธ์ถ
if parent[x] != x:
parent[x] = find_parent(parent, parent[x]) # ๋ถ๋ชจ๋ฅผ ๋ฃจํธ๋
ธ๋๋ก ๋ณ๊ฒฝ
return parent[x]
# ๋ ์์๊ฐ ์ํ ์งํฉ์ ํฉ์น๋ union์ฐ์ฐ
def union_parent(parent, a, b):
a = find_parent(parent, a)
b = find_parent(parent, b)
if a < b:
parent[b] = a
else:
parent[a] = b
# ๋
ธ๋์ ๊ฐ์์ ๊ฐ์ (union ์ฐ์ฐ)์ ๊ฐ์ ์
๋ ฅ๋ฐ๊ธฐ
v, e = map(int, input().split())
# ๋ถ๋ชจํ
์ด๋ธ
parent = [i for i in range(v+1)] # ์ด๊ธฐ ์ํ์์ ๋ชจ๋ ๋
ธ๋์ ๋ฃจํธ๋
ธ๋๋ ์๊ธฐ์์
# ์ฌ์ดํด ๋ฐ์ ์ฌ๋ถ
cycle = False
# ๋ชจ๋ ๊ฐ์ ์ ํ์ธํ๋ฉฐ ์ฌ์ดํด ๋ฐ์ ํ์ธ
for i in range(e):
a,b = map(int, input().split())
# ์ฌ์ดํด์ด ๋ฐ์ํ ๊ฒฝ์ฐ ์ข
๋ฃ
if find_parent(parent, a) == find_parent(parent, b):
cycle = True
break
# ์ฌ์ดํด์ด ๋ฐ์ํ์ง ์์๋ค๋ฉด union ์ํ
else:
union_parent(parent, a, b)
union_parent(parent, a, b)
# ์ฌ์ดํด ๋ฐ์์ฌ๋ถ ์ถ๋ ฅ
if cycle:
print("์ฌ์ดํด์ด ๋ฐ์ํ์ต๋๋ค")
else:
print("์ฌ์ดํด์ด ๋ฐ์ํ์ง ์์์ต๋๋ค")
์ ๋ ฅ | ์ถ๋ ฅ |
3 3 1 2 1 3 2 3 |
์ฌ์ดํด์ด ๋ฐ์ํ์ต๋๋ค |
'์๊ณ ๋ฆฌ์ฆ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์๋ฃ๊ตฌ์กฐ] ์ด์ง ํ์ ํธ๋ฆฌ with Python (0) | 2021.06.21 |
---|---|
[์๋ฃ๊ตฌ์กฐ] ๊ทธ๋ํ (0) | 2021.06.15 |
[์๊ณ ๋ฆฌ์ฆ] ํ๋ก์ด๋ ์์ with Python (0) | 2021.05.23 |
[์๊ณ ๋ฆฌ์ฆ] ๋ค์ต์คํธ๋ผ ์ต๋จ๊ฒฝ๋ก with Python (0) | 2021.05.23 |
[์๊ณ ๋ฆฌ์ฆ] ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ with Python (0) | 2021.05.23 |