Ch10 Graph Theory 10-1
๐ ๋ณต์ต
DFS/BFS์ ์ต๋จ๊ฒฝ๋ก๋ ๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ์ ํ ์ ํ ์ด๋ฉฐ ์ด์ธ์๋ ๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ์ ๊ต์ฅํ ๋ค์ํ๋ฐ, ์ฝ๋ฉ ํ ์คํธ์์ ์ถ์ ๋น์ค์ด ๋ฎ์ง๋ง ๊ผญ ์์์ผ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. 10์ฅ์์ ๋ค๋ฃฐ ์๊ณ ๋ฆฌ์ฆ์ ์์ ๋ฐฐ์ด ๋ด์ฉ์ ๊ธฐ๋ฐํ๋ค.
- ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ(Kruskal Algorithms): ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ํ ์ ํ
- ์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ(Topology Algorithms): ํ ์๋ฃ๊ตฌ์กฐ or ์คํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ํ์ฉํด ๊ตฌํ
๐์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ๋ฅผ ์ ํ์ ๋ ์์๋์ด์ผ ํ ์
- โ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด(ํน์ ๊ฐ์ฒด)๊ฐ ์ฐ๊ฒฐ๋์ด ์๋คโ๋ ์ด์ผ๊ธฐ๋ ๊ฐ์ฅ ๋จผ์ ๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ์ ๋ ์ฌ๋ ค์ผ ํ๋ค.
- ์๋ฅผ๋ค์ด โ์ฌ๋ฌ ๊ฐ์ ๋์๊ฐ ์ฐ๊ฒฐ๋์ด ์๋คโ์ ๊ฐ์ ๋ด์ฉ์ด ๋ฑ์ฅํ๋ฉด ๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ์ ์์ฌํด๋ณด์.
๊ทธ๋ํ ์๋ฃ๊ตฌ์กฐ ์ค์์ ํธ๋ฆฌ(Tree) ์๋ฃ๊ตฌ์กฐ๋ ๋ค์ํ ์๊ณ ๋ฆฌ์ฆ์์ ์ฌ์ฉ๋๋ฏ๋ก ๊ผญ ๊ธฐ์ต.
- ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ๋ ๋ถ๋ชจ -> ์์์ผ๋ก ๋ด๋ ค์ค๋ ๊ณ์ธต์ ์ธ ๋ชจ๋ธ์ด๋ค.
- ํธ๋ฆฌ๋ ์ํ์์๋ ๋ฌด๋ฐฉํฅ ๊ทธ๋ํ๋ก ๊ฐ์ฃผํ์ง๋ง, ์ปดํจํฐ๊ณตํ ๋ถ์ผ์์๋ ๋ฐฉํฅ ๊ทธ๋ํ๋ก ๊ฐ์ฃผํ๋ค.
์์ ๊ทธ๋ํ์ ๊ตฌํ ๋ฐฉ๋ฒ์๋ 2๊ฐ์ง๊ฐ ์๋ค๊ณ ํ๋ค. ๋ ๋ฐฉ์์ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ์ธก๋ฉด์์ ๊ตฌ๋ณ๋๋ค.
- ์ธ์ ํ๋ ฌ(Adjacency Matrix): 2์ฐจ์ ๋ฐฐ์ด์ ์ฌ์ฉํ๋ ๋ฐฉ์
- ๊ฐ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ ์ํด O(Vยฒ)๋งํผ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ํ์
- ํน์ ๋ ธ๋ A์์ ๋ค๋ฅธ ํน์ ๋ ธ๋ B๋ก ์ด์ด์ง ๊ฐ์ ์ ๋น์ฉ์ O(1) ์๊ฐ์ผ๋ก ์ฆ์ ์ ์ ์๋ค.
- ํ๋ก์ด๋ ์์
์๊ณ ๋ฆฌ์ฆ์ ์ธ์ ํ๋ ฌ์ ์ด์ฉ
- ๋ชจ๋ ๋ ธ๋์ ๋ํด ๋ค๋ฅธ ๋ ธ๋๋ก ๊ฐ๋ ์ต์ ๋น์ฉ์ Vยฒ ํฌ๊ธฐ์ 2์ฐจ์ ๋ฆฌ์คํธ์ ์ ์ฅํ ๋ค์, ํด๋น ๋น์ฉ์ ๊ฐฑ์ ํด์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐ
- ์ธ์ ๋ฆฌ์คํธ(Adjacency List): ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์
- ๊ฐ์ ์ ๊ฐ์๋งํผ์ธ O(E)๋งํผ๋ง ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ํ์
- ํน์ ๋ ธ๋ A์์ ๋ค๋ฅธ ํน์ ๋ ธ๋ B๋ก ์ด์ด์ง ๊ฐ์ ์ ๋น์ฉ์ ์๋ ค๋ฉด O(V)๋งํผ์ ์๊ฐ์ด ์์๋๋ค.
- ์ฐ์ ์์ ํ๋ฅผ ์ด์ฉํ๋ ๋ค์ต์คํธ๋ผ ์ต๋จ ๊ฒฝ๋ก ์๊ณ ๋ฆฌ์ฆ์ ์ธ์ ๋ฆฌ์คํธ๋ฅผ ์ด์ฉ
- V๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค์ด์ ๊ฐ ๋ ธ๋์ ์ฐ๊ฒฐ๋ ๋ชจ๋ ๊ฐ์ ์ ๋ํ ์ ๋ณด๋ฅผ ๋ฆฌ์คํธ์ ์ ์ฅ
๐์๊ณ ๋ฆฌ์ฆ ์ ํ์ ์์๋์ด์ผ ํ ์
- ๋ฉ๋ชจ๋ฆฌ์ ์๊ฐ์ ์ผ๋์ ๋๊ณ ์๊ณ ๋ฆฌ์ฆ์ ์ ํํด์ ๊ตฌํํด์ผ ํ๋ค.
- ์๋ฅผ ๋ค์ด, ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ์์ผํ๋ ๋ฌธ์ ๊ฐ ์์ ๋, ๋ ธ๋์ ๊ฐ์๊ฐ ์ ์ ๊ฒฝ์ฐ์๋ ํ๋ก์ด๋ ์์ ์๊ณ ๋ฆฌ์ฆ์, ๋ ธ๋์ ๊ฐ์ ์ ๊ฐ์๊ฐ ๋ง์ ๊ฒฝ์ฐ์๋ ์ฐ์ ์์ ํ๋ฅผ ์ฌ์ฉํ๋ ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ฉด ์ ๋ฆฌํ๋ค.
๐ ์๋ก์ ์งํฉ (Disjoint Sets) ์๊ณ ๋ฆฌ์ฆ
์๋ก์ ์งํฉ (Disjoint Sets)๋ ๊ณตํต ์์๊ฐ ์๋ ๋ ์งํฉ์ ์๋ฏธํ๋ค.
- ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ๋ ์๋ก์ ๋ถ๋ถ ์งํฉ๋ค๋ก ๋๋์ด์ง ์์๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์๋ฃ๊ตฌ์กฐ๋ผ๊ณ ํ ์ ์๋ค.
- ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ๋ ๋ ์ข
๋ฅ์ ์ฐ์ฐ์ ์ง์ํ๋ค.
- ํฉ์งํฉ(Union): ๋ ๊ฐ์ ์์๊ฐ ํฌํจ๋ ์งํฉ์ ํ๋์ ์งํฉ์ผ๋ก ํฉ์น๋ ์ฐ์ฐ์ด๋ค.
- ์ฐพ๊ธฐ(Find): ํน์ ํ ์์๊ฐ ์ํ ์งํฉ์ด ์ด๋ค ์งํฉ์ธ์ง ์๋ ค์ฃผ๋ ์ฐ์ฐ์ด๋ค.
- ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ๋ ํฉ์น๊ธฐ ์ฐพ๊ธฐ(Union Find) ์๋ฃ๊ตฌ์กฐ ๋ผ๊ณ ๋ถ๋ฆฌ๊ธฐ๋ ํ๋ค.
์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ
- ์ฌ๋ฌ ๊ฐ์ ํฉ์น๊ธฐ ์ฐ์ฐ์ด ์ฃผ์ด์ก์ ๋ ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ์ ๋์ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
-
ํฉ์นฉํฉ(Union) ์ฐ์ฐ์ ํ์ธํ์ฌ, ์๋ก ์ฐ๊ฒฐ๋ ๋ ๋ ธ๋ A, B๋ฅผ ํ์ธํ๋ค.
1) A์ B์ ๋ฃจํธ ๋ ธ๋ Aโ, Bโ๋ฅผ ๊ฐ๊ฐ ์ฐพ๋๋ค.
2) Aโ๋ฅผ Bโ์ ๋ถ๋ชจ ๋ ธ๋๋ก ์ค์ ํ๋ค. -
๋ชจ๋ ํฉ์งํฉ(Union) ์ฐ์ฐ์ ์ฒ๋ฆฌํ ๋๊น์ง 1๋ฒ์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
-
- ํฉ์งํฉ ์ฐ์ฐ ์ ์ผ๋ฐ์ ์ผ๋ก ํฐ ๋ฃจํธ ๋ ธ๋๊ฐ ์์ ๋ฃจํธ ๋ ธ๋๋ฅผ ๋ฐ๋ฅด๋ ๊ฒ์ด ๊ดํ์ ์ด๋ค.
์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ: ๋์ ๊ณผ์ ์ดํด๋ณด๊ธฐ
์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ: ์ฐ๊ฒฐ์ฑ
- ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ์์๋ ์ฐ๊ฒฐ์ฑ์ ํตํด ์์ฝ๊ฒ ์งํฉ์ ํํ๋ฅผ ํ์ธํ ์ ์๋ค.
- ๊ธฐ๋ณธ์ ์ธ ํํ์ ์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ์์๋ ๋ฃจํธ ๋
ธ๋์ ์ฆ์ ์ ๊ทผํ ์ ์๋ค.
- ๋ฃจํธ ๋ ธ๋๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ถ๋ชจ ํ ์ด๋ธ์ ๊ณ์ํด์ ํ์ธํ๋ฉฐ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ์ผ ํ๋ค.
์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ: ๊ตฌํ ๋ฐฉ๋ฒ
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ
def find_parent(parent, x):
# ๋ฃจํธ ๋
ธ๋๊ฐ ์๋๋ผ๋ฉด, ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท์ ์ผ๋ก ํธ์ถ
if parent[x] != x:
return find_parent(parent, parent[x])
return x
# ๋ ์์๊ฐ ์ํ ์งํฉ์ ํฉ์น๊ธฐ
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 = [0] * (v + 1) # ๋ถ๋ชจ ํ
์ด๋ธ ์ด๊ธฐํ
# ๋ถ๋ชจ ํ
์ด๋ธ์์์, ๋ถ๋ชจ๋ฅผ ์๊ธฐ ์์ ์ผ๋ก ์ด๊ธฐํ
for i in range(1, v+1):
parent[i] = i
# 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
์๋ก์ ์งํฉ ์๋ฃ๊ตฌ์กฐ: ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ ๋ฐฉ๋ฒ์ ๋ฌธ์ ์
- ํฉ์งํฉ(Union) ์ฐ์ฐ์ด ํธํฅ๋๊ฒ ์ด๋ฃจ์ด์ง๋ ๊ฒฝ์ฐ ์ฐพ๊ธฐ(Find) ํจ์๊ฐ ๋นํจ์จ์ ์ผ๋ก ๋์ํจ
- ์ต์
์ ๊ฒฝ์ฐ์๋ ์ฐพ๊ธฐ(Find) ํจ์๊ฐ ๋ชจ๋ ๋
ธ๋๋ฅผ ๋ค ํ์ธํ๊ฒ ๋์ด ์๊ฐ ๋ณต์ก๋๊ฐ O(V)
- ๋ค์๊ณผ ๊ฐ์ด {1, 2, 3, 4, 5]์ ์ด 5๊ฐ์ ์์๊ฐ ์กด์ฌํ๋ ์ํฉ์ ํ์ธํ์ ๊ฒฝ์ฐ
- ์ํ๋ ์ฐ์ฐ๋ค: Union(4,5), Union(3,4), Union(2,3), Union(1,2)
์๋ก์ ์งํฉ ์๋ฃ ๊ตฌ์กฐ: ๊ฒฝ๋ก ์์ถ
- ์ฐพ๊ธฐ(Find) ํจ์๋ฅผ ์ต์ ํํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก ๊ฒฝ๋ก ์์ถ(Path Compression)์ ์ด์ฉํ ์ ์์
- ์ฐพ๊ธฐ(Find) ํจ์๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํ ๋ค์ ๋ถ๋ชจ ํ ์ด๋ธ ๊ฐ์ ๋ฐ๋ก ๊ฐฑ์
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ
def find_parent(parent, x):
# ๋ฃจํธ ๋
ธ๋๊ฐ ์๋๋ผ๋ฉด, ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท์ ์ผ๋ก ํธ์ถ
if parent[x] != x:
parent[x] = find_parent(parent, parent[x])
return parent[x]
- ๊ฒฝ๋ก ์์ถ ๊ธฐ๋ฒ์ ์ ์ฉํ๋ฉด ๊ฐ ๋ ธ๋์ ๋ํ์ฌ ์ฐพ๊ธฐ(Find) ํจ์๋ฅผ ํธ์ถํ ์ดํ์ ํด๋น ๋ ธ๋์ ๋ฃจํธ ๋ ธ๋๊ฐ ๋ฐ๋ก ๋ถ๋ชจ ๋ ธ๋๊ฐ ๋จ
- ๋์ผํ ์์์ ๋ํด์ ๋ชจ๋ ํฉ์งํฉ(Union) ํจ์๋ฅผ ์ฒ๋ฆฌํ ํ ๊ฐ ์์์ ๋ํ์ฌ ์ฐพ๊ธฐ(Find) ํจ์๋ฅผ ์ํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ชจ ํ ์ด๋ธ์ด ๊ฐฑ์
- ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ ๋นํ์ฌ ์๊ฐ ๋ณต์ก๋๊ฐ ๊ฐ์ ๋จ
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ
def find_parent(parent, x):
# ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท ํธ์ถ
if parent[x] != x:
return find_parent(parent, parent[x])
return parent[x]
# ๋ ์์๊ฐ ์ํ ์งํฉ์ ํฉ์น๊ธฐ
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 = [0] * (v + 1) # ๋ถ๋ชจ ํ
์ด๋ธ ์ด๊ธฐํํ๊ธฐ
# ๋ถ๋ชจ ํ
์ด๋ธ์์์, ๋ถ๋ชจ๋ฅผ ์๊ธฐ ์์ ์ผ๋ก ์ด๊ธฐํ
for i in range(1, v + 1):
parent[i] = i
# 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, 1), 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 1 1 5 5
์๋ก์ ์งํฉ ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐ ๋ณต์ก๋
- ๊ฒฝ๋ก ์์ถ ๋ฐฉ๋ฒ๋ง์ ์ฌ์ฉํ๋ฉฐ ๋ ธ๋์ ๊ฐ์๊ฐ v, ์ต๋ v-1๊ฐ์ union ์ฐ์ฐ๊ณผ m๊ฐ์ find ์ฐ์ฐ์ด ๊ฐ๋ฅํ๋ฉด
- ์๊ฐ ๋ณต์ก๋๋ $O(V + M(1+log_{2-M/V}V))$์ด๋ค.
- ๋ ์งง์ ๋ฐฉ๋ฒ๋ ์กด์ฌํ์ง๋ง ์ฝํ ์์ค์์ ๊ฒฝ๋ก ์์ถ๋ง ์ ์ฉํด๋ ์ถฉ๋ถํ๋ฉฐ ๊ฐ๋ ๋ฐ ๊ตฌํ ๊ฐ๋จํ๋ค.
์๋ก์ ์งํฉ์ ํ์ฉํ ์ฌ์ดํด ํ๋ณ
- ์๋ก์ ์งํฉ์ ๋ฌด๋ฐฉํฅ ๊ทธ๋ํ ๋ด์์์ ์ฌ์ดํด์ ํ๋ณํ ๋ ์ฌ์ฉํ ์ ์๋ค.
- ์ฐธ๊ณ ๋ก ๋ฐฉํฅ ๊ทธ๋ํ์์์ ์ฌ์ดํด ์ฌ๋ถ๋ DFS๋ฅผ ์ด์ฉํ์ฌ ํ๋ณํ ์ ์๋ค.(ํด๋น ๋ด์ฉ์ ์ฑ ์์ ๋ค๋ฃจ์ง ์๋๋ค)
- ์ฌ์ดํด ํ๋ณ ์๊ณ ๋ฆฌ์ฆ์ ๋ค์๊ณผ ๊ฐ๋ค.
-
๊ฐ ๊ฐ์ ์ ํ๋์ฉ ํ์ธํ๋ฉฐ ๋ ๋ ธ๋์ ๋ฃจํธ ๋ ธ๋๋ฅผ ํ์ธํ๋ค.
1) ๋ฃจํธ ๋ ธ๋๊ฐ ์๋ก ๋ค๋ฅด๋ค๋ฉด ๋ ๋ ธ๋์ ๋ํ์ฌ ํฉ์งํฉ(Union) ์ฐ์ฐ์ ์ํํ๋ค.
2) ๋ฃจํธ ๋ ธ๋๊ฐ ์๋ก ๊ฐ๋ค๋ฉด ์ฌ์ดํด(Cycle)์ด ๋ฐ์ํ ๊ฒ์ด๋ค. -
๊ทธ๋ํ์ ํฌํจ๋์ด ์๋ ๋ชจ๋ ๊ฐ์ ์ ๋ํ์ฌ 1๋ฒ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
-
์๋ก์ ์งํฉ์ ํ์ฉํ ์ฌ์ดํด ํ๋ณ: ๋์ ๊ณผ์ ์ดํด๋ณด๊ธฐ
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ
def find_parent(parent, x):
# ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท ํธ์ถ
if parent[x] != x:
return find_parent(parent, parent[x])
return parent[x]
# ๋ ์์๊ฐ ์ํ ์งํฉ์ ํฉ์น๊ธฐ
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 = [0] * (v + 1) # ๋ถ๋ชจ ํ
์ด๋ธ ์ด๊ธฐํํ๊ธฐ
# ๋ถ๋ชจ ํ
์ด๋ธ์์์, ๋ถ๋ชจ๋ฅผ ์๊ธฐ ์์ ์ผ๋ก ์ด๊ธฐํ
for i in range(1, v + 1):
parent[i] = i
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)
if cycle:
print("์ฌ์ดํด์ด ๋ฐ์ํ์ต๋๋ค.")
else:
print("์ฌ์ดํด์ด ๋ฐ์ํ์ง ์์์ต๋๋ค.")
#์
๋ ฅ ์์
3 3
1 2
1 3
2 3
#์ถ๋ ฅ ์์
์ฌ์ดํด์ด ๋ฐ์ํ์ต๋๋ค.
๐ ์ ์ฅํธ๋ฆฌ (Spanning Tree)
- ๊ทธ๋ํ๊ฐ ์์ ๋ ๋ชจ๋ ๋
ธ๋๋ฅผ ํฌํจํ๋ฉด์ ์ฌ์ดํด์ด ์กด์ฌํ์ง ์๋ ๋ถ๋ถ ๊ทธ๋ํ๋ฅผ ์๋ฏธํ๋ค.
- ๋ชจ๋ ๋ ธ๋๊ฐ ํฌํจ๋์ด ์ฐ๊ฒฐ๋๋ฉด์ ์ฌ์ดํด์ด ์กด์ฌํ์ง ์๋๋ค๋ ์กฐ๊ฑด์ ํธ๋ฆฌ์ ์ฑ๋ฆฝ ์กฐ๊ฑด์ด๊ธฐ๋ ํ๋ค.
- ์ ์ฅ ํธ๋ฆฌ๊ฐ ์๋ ๋ถ๋ถ์ 1๋ฒ ๋ ธ๋๊ฐ ํฌํจ๋์ด ์์ง ์์ผ๋ฉฐ, ์ฌ์ดํด์ด ์กด์ฌํ๋ค.
- ์ต์ํ์ ๋น์ฉ์ผ๋ก ๊ตฌ์ฑ๋๋ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ์ฐพ์์ผ ํ ๋ ์ด๋ป๊ฒ ํ ๊น?
- ์๋ฅผ ๋ค์ด N๊ฐ์ ๋์๊ฐ ์กด์ฌํ๋ ์ํฉ์์ ๋ ๋์ ์ฌ์ด์ ๋๋ก๋ฅผ ๋์ ์ ์ฒด ๋์๊ฐ ์๋ก ์ฐ๊ฒฐ๋ ์ ์๋ ๋๋ก๋ฅผ ์ค์นํ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํ๋ค.
- ๋ ๋์ A, B๋ฅผ ์ ํํ์ ๋ A์์ B๋ก ์ด๋ํ๋ ๊ฒฝ๋ก๊ฐ ๋ฐ๋์ ์กด์ฌํ๋๋ก ๋๋ก๋ฅผ ์ค์น
ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ
- ๋ํ์ ์ธ ์ต์ ์ ์ฅ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ
- ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ถ๋ฅ
- ํธ๋ฆฌ์ ์๋ฃ๊ตฌ์กฐ์ด๋ฏ๋ก ๊ฐ์ ์ ๊ฐ์๋ โ๋ ธ๋์ ๊ฐ์-1โ๊ณผ ๊ฐ๋ค.
- ๊ตฌ์ฒด์ ์ธ ๋์ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋น์ฉ์ ๋ฐ๋ผ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ
-
๊ฐ์ ์ ํ๋์ฉ ํ์ธํ๋ฉฐ ํ์ฌ์ ๊ฐ์ ์ด ์ฌ์ดํด์ ๋ฐ์์ํค๋์ง ํ์ธํ๋ค.
1) ์ฌ์ดํด์ด ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ ์ต์ ์ ์ฅ ํธ๋ฆฌ์ ํฌํจํ๋ค.
2) ์ฌ์ดํด์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ ์ต์ ์ ์ฅ ํธ๋ฆฌ์ ํฌํจ์ํค์ง ์๋๋ค. - ๋ชจ๋ ๊ฐ์ ์ ๋ํ์ฌ 2๋ฒ์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ: ๋์ ๊ณผ์
# ํน์ ์์๊ฐ ์ํ ์งํฉ์ ์ฐพ๊ธฐ
def find_parent(x):
# ๋ฃจํธ ๋
ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง ์ฌ๊ท ํธ์ถ
if parent[x] != x:
parent[x] = find_parent(parent[x])
return parent[x]
# ๋ ์์๊ฐ ์ํ ์งํฉ์ ํฉ์น๊ธฐ
def union_parent(a, b):
a = find_parent(a)
b = find_parent(b)
if a < b:
parent[b] = a
else:
parent[a] = b
# ๋
ธ๋์ ๊ฐ์์ ๊ฐ์ (Union ์ฐ์ฐ)์ ๊ฐ์ ์
๋ ฅ ๋ฐ๊ธฐ
v, e = map(int, input().split())
parent = [0] * (v + 1) # ๋ถ๋ชจ ํ
์ด๋ธ ์ด๊ธฐํํ๊ธฐ
# ๋ชจ๋ ๊ฐ์ ์ ๋ด์ ๋ฆฌ์คํธ์, ์ต์ข
๋น์ฉ์ ๋ด์ ๋ณ์
edges = []
result = 0
# ๋ถ๋ชจ ํ
์ด๋ธ ์์์, ๋ถ๋ชจ๋ฅผ ์๊ธฐ ์์ ์ผ๋ก ์ด๊ธฐํ
for i in range(1, v + 1):
parent[i] = i
# ๋ชจ๋ ๊ฐ์ ์ ๋ํ ์ ๋ณด๋ฅผ ์
๋ ฅ ๋ฐ๊ธฐ
for _ in range(e):
a, b, cost = map(int, input().split())
# ๋น์ฉ์์ผ๋ก ์ ๋ ฌํ๊ธฐ ์ํด์ ํํ์ ์ฒซ๋ฒ์งธ ์์๋ฅผ ๋น์ฉ์ผ๋ก ์ค์
edges.append((cost, a, b))
# ๊ฐ์ ์ ๋น์ฉ์์ผ๋ก ์ ๋ ฌ
edges.sort()
# ๊ฐ์ ์ ํ๋์ฉ ํ์ธํ๋ฉฐ
for edge in edges:
cost, a, b = edge
# ์ฌ์ดํด์ด ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ์๋ง ์งํฉ์ ํฌํจ
if find_parent(a) != find_parent(b):
union_parent(a, b)
result += cost
print(result)
#์
๋ ฅ ์์
7 9
1 2 29
1 5 75
2 3 35
2 6 34
3 4 7
4 6 23
4 7 13
5 6 53
6 7 25
#์ถ๋ ฅ ์์
159
ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ: ์ฑ๋ฅ ๋ถ์
- ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ ์ ๊ฐ์๊ฐ E๊ฐ์ผ ๋, O(ElogE)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ค.
- ์๋ํ๋ฉด ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์์ ๊ฐ์ฅ ๋ง์ ์๊ฐ์ ์๊ตฌํ๋ ๊ฒ์ ๊ฐ์ ์ ์ ๋ ฌ์ ์ํํ๋ ๋ถ๋ถ์ด๋ค.
- ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด E๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฌํ๊ธฐ ์ํ ์๊ฐ ๋ณต์ก๋๋ O(ElogE)
๐ ์์ ์ ๋ ฌ (Topology Sort)
- ์ฌ์ดํด์ด ์๋ ๋ฐฉํฅ ๊ทธ๋ํ์ ๋ชจ๋ ๋ ธ๋๋ฅผ โ๋ฐฉํฅ์ฑ์ ๊ฑฐ์ค๋ฅด์ง ์๋๋ก ์์๋๋ก ๋์ดํ๋ ๊ฒโ์ ์๋ฏธ
- ์์) ์ ์๊ณผ๋ชฉ์ ๊ณ ๋ คํ ํ์ต ์์ ์ค์
- ์ ์ธ ๊ณผ๋ชฉ์ ๋ชจ๋ ๋ฃ๊ธฐ ์ํ ์ ์ ํ ํ์ต ์์๋?
- ์๋ฃ๊ตฌ์กฐ -> ์๊ณ ๋ฆฌ์ฆ -> ๊ณ ๊ธ ์๊ณ ๋ฆฌ์ฆ (O)
- ์๋ฃ๊ตฌ์กฐ -> ๊ณ ๊ธ ์๊ณ ๋ฆฌ์ฆ -> ์๊ณ ๋ฆฌ์ฆ (x)
์ง์ ์ฐจ์์ ์ง์ถ์ฐจ์
- ์ง์ ์ฐจ์(Indegree): ํน์ ํ ๋ ธ๋๋ก ๋ค์ด์ค๋ ๊ฐ์ ์ ๊ฐ์
- ์ง์ถ์ฐจ์(Outdegree): ํน์ ํ ๋ ธ๋์์ ๋๊ฐ๋ ๊ฐ์ ์ ๊ฐ์
์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ
- ํ๋ฅผ ์ด์ฉํ๋ ์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ๋์ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค. (DFS๋ก๋ ๊ฐ๋ฅ)
- ์ง์ ์ฐจ์๊ฐ 0์ธ ๋ชจ๋ ๋ ธ๋๋ฅผ ํ์ ๋ฃ๋๋ค.
- ํ๊ฐ ๋น ๋๊น์ง ๋ค์์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
1). ํ์์ ์์๋ฅผ ๊บผ๋ด ํด๋น ๋ ธ๋์์ ๋๊ฐ๋ ๊ฐ์ ์ ๊ทธ๋ํ์์ ์ ๊ฑฐํ๋ค.
2). ์๋กญ๊ฒ ์ง์ ์ฐจ์๊ฐ 0์ด ๋ ๋ ธ๋๋ฅผ ํ์ ๋ฃ๋๋ค.
-> ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ฐ ๋ ธ๋๊ฐ ํ์ ๋ค์ด์จ ์์๊ฐ ์์ ์ ๋ ฌ์ ์ํํ ๊ฒฐ๊ณผ์ ๊ฐ๋ค.
์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ: ๋์ ๊ณผ์
- ์์ ์ ๋ ฌ์ ์ํํ ๊ทธ๋ํ๋ฅผ ์ค๋น
- ์ด๋ ๊ทธ๋ํ๋ ์ฌ์ดํด์ด ์๋ ๋ฐฉํฅ ๊ทธ๋ํ (DAG)์ฌ์ผ ํ๋ค.
- ๋ณธ ์์ ๋ ๋ ์์ ๋ฒํธ์ ๋ ธ๋๊ฐ ์ฐ์ ์ผ๋ก ํ์ ๋ค์ด๊ฐ๊ฒ๋ ๊ฐ์
์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ: ํน์ง
- ์์ ์ ๋ ฌ์ DAG์ ๋ํด์๋ง ์ํํ ์ ์๋ค.
- DAG (Direct Acyclic Graph): ์ํํ์ง ์๋ ๋ฐฉํฅ ๊ทธ๋ํ
- ์์ ์ ๋ ฌ์์๋ ์ฌ๋ฌ ๊ฐ์ง ๋ต์ด ์กด์ฌํ ์ ์๋ค.
- ํ ๋จ๊ณ์์ ํ์ ์๋กญ๊ฒ ๋ค์ด๊ฐ๋ ์์๊ฐ 2๊ฐ ์ด์์ธ ๊ฒฝ์ฐ๊ฐ ์๋ค๋ฉด ์ฌ๋ฌ ๊ฐ์ง ๋ต์ด ์กด์ฌํ ์ ์๋ค.
- ๋ชจ๋ ์์๋ฅผ ๋ฐฉ๋ฌธํ๊ธฐ ์ ์ ํ๊ฐ ๋น๋ค๋ฉด ์ฌ์ดํด์ด ์กด์ฌํ๋ค๊ณ ํ๋จํ ์ ์๋ค.
- ์ฌ์ดํด์ ํฌํจ๋ ์์ ์ค์์ ์ด๋ ํ ์์๋ ํ์ ๋ค์ด๊ฐ์ง ๋ชปํ๋ค.
- ์คํ์ ํ์ฉํ DFS๋ฅผ ์ด์ฉํด ์์ ์ ๋ ฌ์ ์ํํ ์๋ ์๋ค.
from collections import deque
# ๋
ธ๋์ ๊ฐ์์ ๊ฐ์ ์ ๊ฐ์๋ฅผ ์
๋ ฅ ๋ฐ๊ธฐ
v, e = map(int, input().split())
# ๋ชจ๋ ๋
ธ๋์ ๋ํ ์ง์
์ฐจ์๋ 0์ผ๋ก ์ด๊ธฐํ
indegree = [0] * (v + 1)
# ๊ฐ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๊ฐ์ ์ ๋ณด๋ฅผ ๋ด๊ธฐ ์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ์ด๊ธฐํ
graph = [[] for i in range(v + 1)]
# ๋ฐฉํฅ ๊ทธ๋ํ์ ๋ชจ๋ ๊ฐ์ ์ ๋ณด๋ฅผ ์
๋ ฅ ๋ฐ๊ธฐ
for _ in range(e):
a, b = map(int, input().split())
graph[a].append(b) # ์ ์ A์์ B๋ก ์ด๋ ๊ฐ๋ฅ
# ์ง์
์ฐจ์๋ฅผ 1 ์ฆ๊ฐ
indegree[b] += 1
# ์์ ์ ๋ ฌ ํจ์
def topology_sort():
result = [] # ์๊ณ ๋ฆฌ์ฆ ์ํ ๊ฒฐ๊ณผ๋ฅผ ๋ด์ ๋ฆฌ์คํธ
q = deque() # ํ ๊ธฐ๋ฅ์ ์ํ deque ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
# ์ฒ์ ์์ํ ๋๋ ์ง์
์ฐจ์๊ฐ 0์ธ ๋
ธ๋๋ฅผ ํ์ ์ฝ์
for i in range(1, v + 1):
if indegree[i] == 0:
q.append(i)
# ํ๊ฐ ๋น ๋๊น์ง ๋ฐ๋ณต
while q:
# ํ์์ ์์ ๊บผ๋ด๊ธฐ
now = q.popleft()
result.append(now)
# ํด๋น ์์์ ์ฐ๊ฒฐ๋ ๋
ธ๋๋ค์ ์ง์
์ฐจ์์์ 1 ๋นผ๊ธฐ
for i in graph[now]:
indegree[i] -= 1
# ์๋กญ๊ฒ ์ง์
์ฐจ์๊ฐ 0์ด ๋๋ ๋
ธ๋๋ฅผ ํ์ ์ฝ์
if indegree[i] == 0:
q.append(i)
# ์์ ์ ๋ ฌ์ ์ํํ ๊ฒฐ๊ณผ ์ถ๋ ฅ
for i in result:
print(i, end=' ')
topology_sort()
#์
๋ ฅ ์์
7 8
1 2
1 5
2 3
2 6
3 4
4 7
5 6
6 4
#์ถ๋ ฅ ์์
1 2 5 3 6 4 7
์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ: ์ฑ๋ฅ ๋ถ์
- ์์ ์ ๋ ฌ์ ์ํด ์ฐจ๋ก๋๋ก ๋ชจ๋ ๋
ธ๋๋ฅผ ํ์ธํ๋ฉฐ ๊ฐ ๋
ธ๋์์ ๋๊ฐ๋ ๊ฐ์ ์ ์ฐจ๋ก๋๋ก ์ ๊ฑฐํด์ผ ํจ
- ์์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐ ๋ณต์ก๋๋ O(V + E)
๋๊ธ๋จ๊ธฐ๊ธฐ