한 마을에 N개의 집들이 있고, 그 집들을 연결하는 M개의 길이 있다. 각 길마다 길을 유지하는 유지비용이 있다.
이 마을을 두 마을로 분리하고 싶다. 이 때 각 마을에 있는 집들은 서로 연결되어 있어야 한다. 모든 길을 사용할 필요는 없다.
마을을 둘로 나누고 위의 조건을 만족할 때 드는 길의 유지비용의 최솟값을 출력하라.
MST
최소 스패닝 트리는 N개의 노드로 이루어진 연결 그래프에서 모든 노드를 연결하면서 사이클을 만들지 않는 스패닝 트리 중 간선의 가중치 합이 최소가 되는 트리이다.
가중치가 최소가 되고 사이클이 없어야 하므로 N개의 노드를 연결할 때 N-1개의 간선으로 연결되어 있다.
이 문제에서 모든 집을 연결하는 MST를 만든 후, 가장 가중치가 큰 간선 하나를 빼면 마을이 둘로 분리되면서 가중치의 합이 최소가 된다.
Kruskal
Kruskal 알고리즘은 간선 중심으로 MST를 찾는 알고리즘이다.
이 문제에서 MST를 만들고 MST에서 가장 가중치가 큰 간선을 하나 제거하므로써 마을을 둘로 분리할 수 있다.
따라서 기존 Kruskal 알고리즘이 트리에 포함된 간선의 개수가 N-1일 때 while문을 종료했다면,
이 문제는 N-2일 때 while문을 종료하면 된다.
import sys
input = sys.stdin.readline
N, M = map(int, input().split(' '))
parents = [i for i in range(N+1)]
edges = []
for _ in range(M):
edges.append(list(map(int, input().split(' '))))
edges.sort(key=lambda x: x[2])
def find(x):
if x != parents[x]:
parents[x] = find(parents[x])
return parents[x]
def union(a, b):
a = find(a)
b = find(b)
if a < b:
parents[b] = a
else:
parents[a] = b
def kruskal():
total_cost = 0
connected_edges = 0
for [n1, n2, w] in edges:
if connected_edges == N-2:
break
if find(n1) != find(n2):
union(n1, n2)
total_cost += w
connected_edges += 1
return total_cost
print(kruskal())