개요

크루스칼 알고리즘

# 크루스칼로 구현

v, e = map(int, input().split())

edges = [list(map(int, input().split())) for _ in range(e)]
edges.sort(key=lambda x: x[-1]) # 가중치 기준 정렬해주기

parent = [i for i in range(v+1)] # 초기화

# print(edges)
# print(parent)

def get_parent(x):
    if parent[x] == x: # 부모가 자기 자신이다 -> 루트이다.
        return x
    parent[x] = get_parent(parent[x])
    return parent[x]

def union_parent(a, b): # 수가 더 큰 쪽의 부모를, 작은쪽의 부모로 바꾼다 -> 두 간선을 합친다.
    a_root = get_parent(a)
    b_root = get_parent(b)
    if a_root < b_root:
        parent[b_root] = a_root
    else:
        parent[a_root] = b_root

def same_parent(a, b):
    return get_parent(a) == get_parent(b)

result = 0

for a, b, cost in edges:
    if not same_parent(a, b): # 부모가 같다 -> 사이클이 형성되는 것. 부모가 같지 않은 경우에만 한다.
        union_parent(a, b)
        result += cost

print(result)

프림 알고리즘

import sys
import heapq
# 프림으로 구현
v, e = map(int, sys.stdin.readline().split())

edges = [[] for i in range (v+1)]
visited = [0] * (v+1)

def prim() :
    ret = 0
    min_heap =[]
    heapq.heappush(min_heap, (0, 1)) # 최소 스패닝 트리는 어디서 시작하든 상관없다. (애초에 전제가 모든 vertex를 다 돌아야 하는 거니깐.)
    
    while min_heap :
        cost, vertex = heapq.heappop(min_heap)
        
        if visited[vertex] : # 방문검사를 아래에서 하긴 했지만, 가중치 더 작은 edge에 의해 해당 vertex가 이미 선점되었을 수 있다. 즉 한번 더해준다.
            continue
        visited[vertex] = 1

        ret += cost
        
        for edge in edges[vertex] :
            if visited[edge[1]] == 1 :
                continue
            heapq.heappush(min_heap, edge) # 현재 만들어진 트리에서 갈 수 있는 경우의 수를 하나씩 더해나간다고 생각하자. 우리는 그중에서 가중치가 가장 작은 것들만 뽑을거다.
        
    return ret

for _ in range (e) :
    a, b, c = map(int, sys.stdin.readline().split())
    edges[a].append((c, b))
    edges[b].append((c, a))

print(prim())

참고

https://huiung.tistory.com/76

크루스칼 VS 프림 파헤치기