์๋ฃ๊ตฌ์กฐ/๐์๊ณ ๋ฆฌ์ฆ - 24
์ค๋ ๋ค์ ๊ฐ์ ๋ชฉ๋ก
- Union Find
- ํฌ๋ฃจ์ค์นผ - 1 : Union-by-Rank
Union Find ์ต์ ํ
์ ๋ฒ ํฌ์คํธ์์ ์ต์
์ ๊ฒฝ์ฐ๋ฅผ ๊ตฌํํ๊ธฐ ๊น์ง ํ๋ค.
์ด์ ์ด๋ฐ ์ต์
์ ๊ฒฝ์ฐ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ต์ ํ ๊ธฐ๋ฒ ๋๊ฐ์ง๋ฅผ ์๊ฐํ๊ฒ ๋ค.
- union-by-rank
- path-compression : ๊ฒฝ๋ก์์ถ
Unionํจ์์์ ์ต์ ํ : union-by-rank
๊ฐ ๋์ด๋ณ๋ก ๋ญํฌ๋ฅผ ๋ถ์ฌํ์ฌ, Unionํ ๋ ๋ ์งํฉ์ ์ต๋ ๋
ธ๋๋ฅผ ๋น๊ตํ๊ณ ,
๋ ๋์ ๋ญํฌ๋ฅผ ๊ฐ์ง ์งํฉ์ ๋ฎ์ ๋ญํฌ๋ฅผ ๊ฐ์ง ์งํฉ์ ๋ถ์ด๋ ๋ฐฉ๋ฒ.
์๊ฐ๋ณต์ก๋ : ์ต์
์ ๊ฒฝ์ฐ์์ leaf๋
ธ๋(์ตํ์ ๋
ธ๋)๋ฅผ ์ด์ฉํด union/find์ฐ์ฐ์ ๊ฒฝ์ฐ ๋์ด๊ฐ $N$์ด๋ผ์ $O(N)$์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋๋ฐ,
์ด ๋ฐฉ๋ฒ์ ์ด์ฉํ๋ฉด ์ต์
์ ๊ฒฝ์ฐ์๋ ๋์ด๊ฐ $log N$์ผ๋ก $O(log N)$์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๊ฒ ๋๋ค.
- ๋ ์งํฉ A, B์์ ํ ์งํฉ์ ๋ญํฌ๊ฐ ๋์ ๊ฒฝ์ฐ,
๋ญํฌ๊ฐ ๋์ ์งํฉ์ ๋ฎ์ ์งํฉ์ ๋ถ์ธ๋ค.- ๋ ์งํฉ A, B์์ ๋ ์งํฉ์ ๋ญํฌ๊ฐ ๊ฐ์ ๊ฒฝ์ฐ,
ํ ์งํฉ์ ๋ญํฌ๋ฅผ ์ฌ๋ฆฌ๊ณ , ๋ค๋ฅธ ์งํฉ์ ๋ถ์ธ๋ค.
union-by-rank ๊ตฌํ
union-by-rank ๊ตฌํ์ ์ํด์๋ rank๋ผ๋ ๊ณต๊ฐ์ด ํ์ํ๋ค.
๊ฐ ๋
ธ๋๋ ๋ญํฌ๊ฐ์ ๊ฐ์ง๊ณ , ๋ญํฌ์ ํ๋ณ์ ์ต์์ ๋
ธ๋์ ๋ญํฌ๋ก ํ๋ณํ๋ฉด ๊ฐ๋จํ๋ค.
from string import ascii_uppercase
parentOf = {v : v for v in ascii_uppercase[:6]}
rank = {v : 0 for v in ascii_uppercase[:6]}
def Find(node):
if parentOf[node] != node:
return Find(parentOf[node])
return node
def Union (n1, n2):
p1 = Find(n1)
p2 = Find(n2)
if p1 == p2:
return
# union-by-rank ๊ตฌํ
if rank[p1] < rank[p2]:
parentOf[p1] = p2
elif rank[p1] > rank[p2]:
parentOf[p2] = p1
else:
rank[p1] += 1
parentOf[p2] = p1
Union('E', 'F')
Union('D', 'E')
Union('C', 'D')
Union('B', 'C')
Union('A', 'B')
print(parentOf)
์ต์ ์ ๊ฒฝ์ฐ๋ก ๋ํ๋ฌ๋ ๊ฒ์ด 1์ ๋ญํฌ๋ฅผ ๊ฐ์ง๋ ์งํฉ์ด ๋์๋ค.
Findํจ์์์ ์ต์ ํ : path-compression
๊ฒฝ๋ก์์ถ์ด๋ผ๊ณ ํ๋ฉฐ, Find๋ฅผ ์คํํ ๋ ธ๋์, ํ๊ณ ์ฌ๋ผ๊ฐ ๋ ธ๋๋ค์ ๋ฃจํธ ๋ ธ๋์ ๋ฐ๋ก ์ฐ๊ฒฐํ์ฌ ๋ค์ Find ์ฐ์ฐ์ ํ์ ํ์๋ฅผ ์ค์ด๋ ๋ฐฉ๋ฒ
์๊ฐ๋ณต์ก๋ : union-by-rank๋ฅผ ๊ตฌํํ์๋, $O(log N)$์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ค๊ณ ํ๋๋ฐ,
path-compression์ ๊ตฌํํ์ ๋๋, $O(1)$์ ์๊ฐ๋ณต์ก๋์ ๊ฐ๊น๋ค.
path-compression ๊ธฐ๋ฒ์ ๊ฐ๋จํ๊ฒ ์ ์ฉํ๊ธฐ ์ํด์ Findํจ์๋ฅผ ์ฌ๊ทํจ์๋ก ๊ตฌํํ๋ค.
path-compression ๊ตฌํ
path-compression์ ๊ฐ๋จํ๊ฒ ๊ตฌํ๋๋ค.
๊ธฐ์กด์๋ Find(parentOf[node])์ ๋ฐํ๊ฐ์ ๋ฐ๋ก ๋ฐํํ๋๋ฐ,
์ด ๊ฐ์ parentOf[node]์ ์ ์ฅํ๋ฉด์ ๋ฐํํ๋ฉด ๋๋ค.
from string import ascii_uppercase
parentOf = {v : v for v in ascii_uppercase[:6]}
rank = {v : 0 for v in ascii_uppercase[:6]}
def Find(node):
if parentOf[node] != node:
# path-compression
parentOf[node] = Find(parentOf[node])
return parentOf[node]
def Union (n1, n2):
p1 = Find(n1)
p2 = Find(n2)
if p1 == p2:
return
# union-by-rank ๊ตฌํ
if rank[p1] < rank[p2]:
parentOf[p1] = p2
elif rank[p1] > rank[p2]:
parentOf[p2] = p1
else:
rank[p1] += 1
parentOf[p2] = p1
Union('A', 'B')
Union('C', 'D')
Union('A', 'D')
Union('E', 'F')
Union('D', 'F')
print(parentOf)
print(Find('F'))
print(parentOf)
D์ ๋ถ๋ชจ๊ฐ C๊ฐ ์๋ A๋ค.
Union(โDโ, โFโ)์์ Find(โDโ)๋ฅผ ์คํํ๋ฉด์ ๊ฒฝ๋ก์์ถ์ผ๋ก A๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋์๋ค.
๋ง์ง๋ง
Unionํจ์๋ ๋ค์์๊ฐ์ ๊ตฌํ??? ํ๋ค๊ณ ํ๋ค???
??? : ์ ์๋ ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ด๋ผ๋ฉด์์ ๋ถ๋ช
์ ๋ชฉ์ ํฌ๋ฃจ์ค์นผ์ด๋ฌ๋๋ฐโฆ
2020-11-18 ์์
unionํจ์์์ ๊ฐ์ ์งํฉ์ผ๋, ํฉ์น์ง ์๋ ๋ถ๋ถ์ ์์จ๋จ๋ค.
Find์ดํ ์๋ ์ฝ๋๋ง ์ถ๊ฐํ๋ฉด ๋๋ค.
if p1 == p2:
return
๋๊ธ๋จ๊ธฐ๊ธฐ