크루스칼 알고리즘(Kruskal Algorithm), 최소 신장 트리(MST)

2022년 12월 22일

  • 모든 정점을 포함하고 사이클이 없는 연결 선을 그릴 때, 가중치의 합이 최소가 되는 상황에 사용

신장 트리(Spanning Tree)

  • 모든 정점(vertex)이 연결
  • 정점 간 서로 연결이되고, 싸이클이 존재하지 않는 그래프
  • n개의 정점을 모두 연결할 수 있는 n-1개의 엣지로 이루어진 부분 그래프

최소 신장 트리(Minimum Spanning Tree, MST)

  • 신장 트리 집합 중 가중치의 합이 최소가 되는 신장 트리

-> 크루스칼 알고리즘은 최소 신장 트리를 구할 때 사용


크루스칼 알고리즘(Kruskal Algorithm)

  • 그리디 알고리즘의 일종
  • 그래프의 간선들을 가중치의 오름차순으로 정렬
  • 사이클이 형성되지 않으면서 정렬된 순서로 간선을 선택

사이클 판단하기 - Union & Find

  • Disjoint Set(서로소 집합)을 표현하는 자료구조
  • 서로 다른 두 집합을 병합하는 Union 연산
  • 집합 원소가 어떤 집합에 속해있는지를 찾는 Find 연산
kruskal.py
# 크루스칼 알고리즘
# vertex가 어떤 집합에 속해있는지 찾아줌 
def find(parent,vertex):
    if parent[vertex] != vertex:
            parent[vertex] = find(parent,parent[vertex])
    return parent[vertex]
# vertex a와 b를 같은 집합으로 합쳐줌, a와 b의 집합 중 더 작은 값이 그룹을 나타냄
def union(parent,a,b):
    a = find(parent,a)
    b = find(parent,b)
    if a<b:
        parent[b]=a
    else:
        parent[a]=b
def solution(n,weights):
    answer=0
    weights.sort(가중치에 대한 오름차순 정렬)
    parent=[i for i in range(n)]
    # edge
    for edge in edges:
        # edge 표현 start-end-weight
        start,end,weight
        # start-end의 집합 확인
        a = find(parent,start)
        b = find(parent,end)
        # a와 b가 다른 집합이면 union(싸이클 생성x)
        if a!=b:
            union(parent,a,b)
            answer+=weight
    return answer

예제)image

  1. 간선들을 가중치에 따라 정렬, 어떤 집합에 속해있는지에 대한 배열(초기에는 자기 자신)
  • 가중치에 따라 정렬된 가중치 배열 image
  • 어떤 집합에 속해 있는지 나타내는 parent 배열 image
  1. 가중치 배열에 따라 싸이클이 생기지 않도록 간선 선택
    a. 노드 1과 2의 parent가 다르므로 간선 1-2 추가, 노드 2의 parent -> 1 image
    b. 노드 2와 4의 parent가 다르므로 간선 2-4 추가, 4의 parent -> 1 image
    c. 노드 1과 5의 parent가 다르므로 간선 1-5 추가 5의 parent ->1 image d. 노드 4와 5의 parent는 같으므로 간선 4-5는 추가하지 않는다.
    image e. 노드 3과 5의 parent가 다르므로 간선 3-5 추가 image

-> 5개의 정점이 4개의 간선으로 모두 연결된 최소 신장 트리


댓글