Skip to content

Latest commit

ย 

History

History
132 lines (101 loc) ยท 4.34 KB

MST.md

File metadata and controls

132 lines (101 loc) ยท 4.34 KB

๐ŸŒฒ Minimum Spanning Tree/์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ

Minimum Spanning Tree๋ž€?

๊ทธ๋ž˜ํ”„ G์˜ spanning tree ์ค‘ ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์ด ์ตœ์†Œ์ธ spanning tree๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

MST์˜ ํŠน์ง•

  • ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์ด ์ตœ์†Œ์—ฌ์•ผ ํ•œ๋‹ค.
  • n๊ฐœ์˜ ์ •์ ์„ ๊ฐ€์ง€๋Š” ๊ทธ๋ž˜ํ”„์— ๋Œ€ํ•ด ๋ฐ˜๋“œ์‹œ (n-1)๊ฐœ์˜ ๊ฐ„์„ ๋งŒ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • ์‚ฌ์ดํด์ด ํฌํ•จ๋˜์–ด์„œ๋Š” ์•ˆ๋œ๋‹ค. spanning tree : ๊ทธ๋ž˜ํ”„ ๋‚ด์— ์žˆ๋Š” ๋ชจ๋“  ์ •์ ์„ ์—ฐ๊ฒฐํ•˜๊ณ  ์‚ฌ์ดํด์ด ์—†๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

Kruskal ์•Œ๊ณ ๋ฆฌ์ฆ˜

ํƒ์š•์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐ€์ค‘์น˜๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ชจ๋“  ์ •์ ์„ ์ตœ์†Œ ๋น„์šฉ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ์ตœ์ ์˜ ํ•ด๋‹ต์„ ์ฐพ๋Š” ๋ฐฉ์‹์ด๋‹ค.

  • ์ตœ์†Œ ๋น„์šฉ์˜ ๊ฐ„์„ ์œผ๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ ์‚ฌ์ดํด์„ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ๊ฐ ๋‹จ๊ณ„์—์„œ ์‚ฌ์ดํด์„ ์ด๋ฃจ์ง€ ์•Š๋Š” ์ตœ์†Œ ๋น„์šฉ ๊ฐ„์„  ์„ ํƒ
  • ๊ฐ„์„  ์„ ํƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.
  • ์ด์ „ ๋‹จ๊ณ„์—์„œ ๋งŒ๋“ค์–ด์ง„ ์‹ ์žฅ ํŠธ๋ฆฌ์™€๋Š” ๊ด€๋ จ์—†์ด ๋ฌด์กฐ๊ฑด ์ตœ์†Œ ๊ฐ„์„ ๋งŒ์„ ์„ ํƒ
  • union-find ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•˜๋ฉฐ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ๊ฐ„์„ ์„ ์ •๋ ฌํ•˜๋Š” ์‹œ๊ฐ„์— ์ขŒ์šฐ๋œ๋‹ค.
  • O(ElogE + E)

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฝ”๋“œ
import sys

v, e = map(int, input().split())
# ๋ถ€๋ชจ ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”
parent = [0] * (v+1)
for i in range(1, v+1):
    parent[i] = i

# ๋ถ€๋ชจ๋ฅผ ์ฐพ๋Š” ์—ฐ์‚ฐ 
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

# ๊ฐ„์„  ์ •๋ณด ๋‹ด์„ ๋ฆฌ์ŠคํŠธ์™€ ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ ๊ณ„์‚ฐ ๋ณ€์ˆ˜ ์ •์˜
edges = []
total_cost = 0

# ๊ฐ„์„  ์ •๋ณด ์ฃผ์–ด์ง€๊ณ  ๋น„์šฉ์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
for _ in range(e):
    a, b, cost = map(int, input().split())
    edges.append((cost, a, b))

# ๊ฐ„์„  ์ •๋ณด ๋น„์šฉ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ
edges.sort()

# ๊ฐ„์„  ์ •๋ณด ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜๋ฉด์„œ ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ˆ˜ํ–‰
for i in range(e):
    cost, a, b = edges[i]
    # find ์—ฐ์‚ฐ ํ›„, ๋ถ€๋ชจ๋…ธ๋“œ ๋‹ค๋ฅด๋ฉด ์‚ฌ์ดํด ๋ฐœ์ƒ X์œผ๋ฏ€๋กœ union ์—ฐ์‚ฐ ์ˆ˜ํ–‰ -> ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ์— ํฌํ•จ!
    if find_parent(parent, a) != find_parent(parent, b):
        union_parent(parent, a, b)
        total_cost += cost

print(total_cost)


Prim ์•Œ๊ณ ๋ฆฌ์ฆ˜

์‹œ์ž‘ ์ •์ ์—์„œ ๋ถ€ํ„ฐ ์ถœ๋ฐœํ•˜์—ฌ ์‹ ์žฅํŠธ๋ฆฌ ์ง‘ํ•ฉ์„ ๋‹จ๊ณ„์ ์œผ๋กœ ํ™•์žฅํ•ด๋‚˜๊ฐ€๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

  • ์ •์  ์„ ํƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.
  • ์ด์ „ ๋‹จ๊ณ„์—์„œ ๋งŒ๋“œ๋ ์ง„ ์‹ ์žฅํŠธ๋ฆฌ๋ฅผ ์ ์  ํ™•์žฅํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. (ํฌ๋ฃจ์Šค์นผ์€ ์ด์ „ ์‹ ์žฅํŠธ๋ฆฌ์™€๋Š” ์—ฐ๊ด€์ด ์—†์Œ.)
  • ์‹œ๊ฐ„ ๋ณต์žก๋„์— ๊ฐ€์žฅ ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒƒ์€ ๊ฐ€์ค‘์น˜๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ์ •์ ์„ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ๊ณผ ์ธ์ ‘ํ•œ ์ •์ ์˜ ํƒ์ƒ‰์ด๋‹ค.
  • ๋ชจ๋“  ๋…ธ๋“œ์— ๋Œ€ํ•ด ํƒ์ƒ‰ O(V)์ด๊ณ  ์šฐ์„  ์ˆœ์œ„ํ ์‚ฌ์šฉ์œผ๋กœ O(logV) ์ตœ์ข… ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(ElogV)์ด๋‹ค.
ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฝ”๋“œ
import heapq
import collections
import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

n, m = map(int,input().split()) # ๋…ธ๋“œ ์ˆ˜, ๊ฐ„์„  ์ˆ˜
graph = collections.defaultdict(list) # ๋นˆ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
visited = [0] * (n+1) # ๋…ธ๋“œ์˜ ๋ฐฉ๋ฌธ ์ •๋ณด ์ดˆ๊ธฐํ™”

# ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
for i in range(m): # ๊ฐ„์„ฑ ์ •๋ณด ์ž…๋ ฅ ๋ฐ›๊ธฐ
    u, v, weight = map(int,input().split())
    graph[u].append([weight, u, v])
    graph[v].append([weight, v, u])


# ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜
def prim(graph, start_node):
    visited[start_node] = 1 # ๋ฐฉ๋ฌธ ๊ฐฑ์‹ 
    candidate = graph[start_node] # ์ธ์ ‘ ๊ฐ„์„  ์ถ”์ถœ
    heapq.heapify(candidate) # ์šฐ์„ ์ˆœ์œ„ ํ ์ƒ์„ฑ
    mst = [] # mst
    total_weight = 0 # ์ „์ฒด ๊ฐ€์ค‘์น˜

    while candidate:
        weight, u, v = heapq.heappop(candidate) # ๊ฐ€์ค‘์น˜๊ฐ€ ๊ฐ€์žฅ ์ ์€ ๊ฐ„์„  ์ถ”์ถœ
        if visited[v] == 0: # ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด
            visited[v] = 1 # ๋ฐฉ๋ฌธ ๊ฐฑ์‹ 
            mst.append((u,v)) # mst ์‚ฝ์ž…
            total_weight += weight # ์ „์ฒด ๊ฐ€์ค‘์น˜ ๊ฐฑ์‹ 

            for edge in graph[v]: # ๋‹ค์Œ ์ธ์ ‘ ๊ฐ„์„  ํƒ์ƒ‰
                if visited[edge[2]] == 0: # ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, (์ˆœํ™˜ ๋ฐฉ์ง€)
                    heapq.heappush(candidate, edge) # ์šฐ์„ ์ˆœ์œ„ ํ์— edge ์‚ฝ์ž…

    return total_weight

print(prim(graph,1))