신장 트리
그래프 내의 모든 정점을 포함하는 트리(Tree) = 최소 연결 부분 그래프(Graph)
즉, 그래프에서 모든 정점에 대한 최소한의 연결만을 남긴 트리
- DFS, BFS를 이용하여 그래프에서 신장 트리를 찾을 수 있음 ( 탐색 중 사용된 간선만 합 )
- 하나의 그래프에는 많은 신장 트리가 존재할 수 있음
- 모든 정점들이 연결되어 있어야 하고, 사이클을 포함해선 안됨
- n개의 정점을 가지는 그래프의 최소 간선의 수는 (n-1)개
= 그래프가 (n-1)의 간선으로 연결되어 있으면 필연적으로 트리 형태
= 그것이 스패닝 트리 (= Spanning Tree)
최소 (비용) 신장 트리
신장 트리들 중 간선의 가중치 합이 가장 작은 트리(Tree)
각 간선의 가중치가 동일하지 않을 때, 가장 적은 간선을 사용하는 것이 최소 비용이 아님
MST는 간선 간의 가중치를 고려하여 최소비용의 Spanning Tree를 선택
= 모든 정점들을 가장 적은 수의 간선과 비용으로 연결하는 것
[ 활용 예시 ]
- 크루스칼 알고리즘 (Kruskal Algorithm)
- 프림 알고리즘 (Prim Algorithm)
- 솔린 알고리즘 (Solling Algorithm)
탐욕 기법(Greedy Algorithm) 을 이용하여 네트워크(가중치를 간선에 할당한 그래프)의 모든 정점을 최소 비용으로 연결하는 최적 해답을 구하는 것
1) 최소 비용의 간선으로 구성됨
2) 사이클을 포함하지 않음
[ 간선의 개수 = E ]
탐색 : O(상수)
정렬 : O( E log E )
import sys
input = sys.stdin.readline
# vertexs[a]가 a가 아닌 경우(vertexs 리스트는 value가 인덱스 번호 순으로 되어있음)
# vertex[a]에 할당되어 있는 값을 리턴
def find_node(vertexs, a):
if vertexs[a] != a:
vertexs[a] = find_node(vertexs, vertexs[a])
return vertexs[a]
def union_node(vertexs, a, b):
a = find_node(vertexs, a)
b = find_node(vertexs, b)
if a < b:
vertexs[b] = a
else:
vertexs[a] = b
node, edge = map(int, input().split())
edges = []
result = 0
# 1부터 node 까지 노드배열 생성
vertexs = [ i for i in range(node+1)]
for _ in range(edge):
# 시작 노드, 도착 노드, 노드 사이의 가중치를 저장
start, end, weight = map(int, input().split())
edges.append([start, end, weight])
# 가중치를 기준으로 오름차순 정렬
edges.sort(key=lambda edge: edge[2])
# 사이클이 발생하지 않을 때만 집합에 포함
for start, end, weight in edges:
if find_node(vertexs, start) != find_node(vertexs, end):
union_node(vertexs, start, end)
result += weight
sys.stdout.write(str(result))
시작 정점에서부터 출발하여 신장트리 집합을 단계적으로 확장 해나가는 방법