์ฝ”ํ…Œ

ํŒŒ์ด์ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ณต๋ถ€ - (5) ๊ธฐํƒ€ (์„œ๋กœ์†Œ ์ง‘ํ•ฉ, ์‹ ์žฅํŠธ๋ฆฌ, ์œ„์ƒ์ •๋ ฌ)

sueeee-e 2025. 2. 5. 21:14

 

๐Ÿ“์„œ๋กœ์†Œ ์ง‘ํ•ฉ

: ๊ณตํ†ต ์›์†Œ๊ฐ€ ์—†๋Š” ๋‘ ์ง‘ํ•ฉ์„ ์˜๋ฏธํ•จ

- ํ•ฉ์ง‘ํ•ฉ(Union) : ๋‘ ๊ฐœ์˜ ์›์†Œ๊ฐ€ ํฌํ•จ๋œ ์ง‘ํ•ฉ์„ ํ•˜๋‚˜์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ•ฉ์น˜๋Š” ์—ฐ์‚ฐ

- ์ฐพ๊ธฐ(Find) : ํŠน์ •ํ•œ ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์ด ์–ด๋–ค ์ง‘ํ•ฉ์ธ์ง€ ์•Œ๋ ค์ฃผ๋Š” ์—ฐ์‚ฐ

์„œ๋กœ์†Œ ์ง‘ํ•ฉ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๋‘ ์ข…๋ฅ˜์˜ ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค.

 

ํ•ฉ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ด ํŽธํ–ฅ๋˜๊ฒŒ ์ด๋ฃจ์–ด์งˆ ๊ฒฝ์šฐ ๋น„ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘

์ตœ์•…์˜ ๊ฒฝ์šฐ ์‹œ๊ฐ„๋ณต์žก๋„ : O(V) (๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ๋‹ค ํ™•์ธํ•ด์•ผ ํ•จ)

#ํŠน์ • ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์„ ์ฐพ๊ธฐ
def find_parent(parent, x):
	if parent[x] != x: #๋ฃจํŠธ ๋…ธ๋“œ๋ฅผ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ์žฌ๊ท€ํ˜ธ์ถœ
    	return find_parent(parent, parent[x])
    return x
    
# 2. ๊ฒฝ๋กœ ์••์ถ• ๋ฐฉ๋ฒ•์œผ๋กœ 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

#๋…ธ๋“œ๊ฐœ์ˆ˜, ๊ฐ„์„  ์ž…๋ ฅ๋ฐ›๊ธฐ
v, e = map(int, input().split())
parent = [0] *(v+1)

for i in range(1, v+1):
	parent[i] = i
    
for i in range(e):
	a, b = map(int, input().split())
    union_parent(parent, a, b)
    
# ๊ฐ ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ 
for i in range(1, v+1):
	print(find_parent(parent, i), end='')
    
# ๋ถ€๋ชจ ํ…Œ์ด๋ธ” ๋‚ด์šฉ ์ถœ๋ ฅ
for i in range(1, v+1):
	print(parent[i], end='')

 

 

์„œ๋กœ์†Œ ์ง‘ํ•ฉ์„ ์ด์šฉํ•˜์—ฌ ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„ ๋‚ด์—์„œ์˜ ์‚ฌ์ดํด์„ ํŒ๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. 

(*๋ฐฉํ–ฅ๊ทธ๋ž˜ํ”„ ํŒ๋ณ„์€ DFS)

1. ๊ฐ ๊ฐ„์„ ์„ ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜๋ฉฐ ๋‘ ๋…ธ๋“œ์˜ ๋ฃจํŠธ ๋…ธ๋“œ๋ฅผ ํ™•์ธ, ๋‹ค๋ฅด๋‹ค๋ฉด ํ•ฉ์ง‘ํ•ฉ ์—ฐ์‚ฐ ์ˆ˜ํ–‰ / ๊ฐ™๋‹ค๋ฉด ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•œ ๊ฒƒ

2. ๊ทธ๋ž˜ํ”„์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๋ชจ๋“  ๊ฐ„์„ ์— ๋Œ€ํ•˜์—ฌ 1๋ฒˆ ๋ฐ˜๋ณต

 

๋ฃจํŠธ ๋…ธ๋“œ๊ฐ€ ๋‹ค ๊ฐ™๋‹ค๋ฉด ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•œ ๊ฒƒ

 

for i in range(e):
	a, b = map(int, input().split())
    if find_parent(parent, a) == find_parent(parent, b):
    	cycle = True
        break
    else:
    	union_parent(parent, a, b)

 

๐Ÿ“์‹ ์žฅ ํŠธ๋ฆฌ

: ๊ทธ๋ž˜ํ”„์—์„œ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํฌํ•จํ•˜๋ฉด์„œ ์‚ฌ์ดํด์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„ ๊ทธ๋ž˜ํ”„๋ฅผ ์˜๋ฏธ

 

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜

- ๋Œ€ํ‘œ์ ์ธ ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜, ๊ทธ๋ฆฌ๋”” ์•Œ๊ณ ๋ฆฌ์ฆ˜

1. ๊ฐ„์„  ๋ฐ์ดํ„ฐ๋ฅผ ๋น„์šฉ์— ๋”ฐ๋ผ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ

2. ๊ฐ„์„ ์„ ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜๋ฉฐ ํ˜„์žฌ์˜ ๊ฐ„์„ ์ด ์‚ฌ์ดํด์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š”์ง€ ํ™•์ธ ( ์‚ฌ์ดํด ๋ฐœ์ƒ X :์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ์— ํฌํ•จ, ์‚ฌ์ดํด ๋ฐœ์ƒ : ํฌํ•จ X)

3. ๋ชจ๋“  ๊ฐ„์„ ์— ๋Œ€ํ•ด 2๋ฒˆ ๋ฐ˜๋ณต

- ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜๊ฐ€ E๊ฐœ์ผ ๋•Œ ์‹œ๊ฐ„๋ณต์žก๋„ : O(ElogE)

# find_parent(parent, x), union_parent(parent, a, b) ํ™œ์šฉ
# ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜

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(parent, a) != find_parent(parent, b):
    	union_parent(parent, a, b)
    	result += cost
   
return result

๐Ÿ“์œ„์ƒ ์ •๋ ฌ

: ์‚ฌ์ดํด์ด ์—†๋Š” ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ๋ฐฉํ–ฅ์„ฑ์— ๊ฑฐ์Šค๋ฅด์ง€ ์•Š๋„๋ก ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธ

- ํ๋ฅผ ์ด์šฉํ•˜๋Š” ์œ„์ƒ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

1. ์ง„์ž…์ฐจ์ˆ˜๊ฐ€ 0์ธ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํ์— ๋„ฃ๋Š”๋‹ค. 

1-1. ํ์—์„œ ์›์†Œ๋ฅผ ๊บผ๋‚ด ํ•ด๋‹น ๋…ธ๋“œ์—์„œ ๋‚˜๊ฐ€๋Š” ๊ฐ„์„  ๊ทธ๋ž˜ํ”„๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.

1-2. ์ƒˆ๋กญ๊ฒŒ ์ง„์ž…์ฐจ์ˆ˜๊ฐ€ 0์ด ๋œ ๋…ธ๋“œ๋ฅผ ํ์— ๋„ฃ๋Š”๋‹ค. 

2. ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

 

*์ง„์ž…์ฐจ์ˆ˜: ํŠน์ •ํ•œ ๋…ธ๋“œ๋กœ ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜

*์ง„์ถœ์ฐจ์ˆ˜: ํŠน์ •ํ•œ ๋…ธ๋“œ์—์„œ ๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜

 

- ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋‹ต์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๋ชจ๋“  ์›์†Œ๋ฅผ ๋ฐฉ๋ฌธํ•˜๊ธฐ ์ „์— ํ๊ฐ€ ๋นˆ๋‹ค๋ฉด ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค๊ณ  ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. 

- ์Šคํƒ์œผ๋กœ ์ด์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 

- ์‹œ๊ฐ„ ๋ณต์žก๋„ : O(V+E)

 

from collections import deque

v, e = map(int, input().split())
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)
    indegree[b] += 1
    
# ์œ„์ƒ์ •๋ ฌ ํ•จ์ˆ˜
def topology_sort():
	result = []
    q = deque()
    for i in range(1, v+1):
    	if indegree[i] == 0:
        	q.append(i)
    # ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
    while q:
    	now = q.popleft()
        result.append(now)
        for i in graph[now]:
        	indegree[i] -= 1
            if indegree[i] == 0:
            	q.append(i)
    for i in result:
    	print(i, end='')
        
topology_sort()