1197 - 최소 스패닝 트리
info
- 문제 보기: 1197 - 최소 스패닝 트리
- 소요 시간: 14분
- 풀이 언어:
python
- 체감 난이도: 2️⃣~3️⃣
- 리뷰 횟수: ✅
풀이 키워드
스포주의
그래프
최소스패닝트리
유니온파인드
풀이 코드
info
- 메모리: 50664 KB
- 시간: 304 ms
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
parent = []
def union(a, b):
global parent
pa = find(a)
pb = find(b)
if pa < pb:
parent[pb] = pa
else:
parent[pa] = pb
def find(x):
global parent
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def solution():
global parent
V, E = map(int, input().split())
parent = [x for x in range(V+1)] # for union-find
tree = []
for _ in range(E):
a, b, weight = list(map(int, input().split()))
tree.append((weight, a, b))
# Kruskal
ans = 0
tree.sort()
for data in tree:
weight, a, b = data
if find(a) != find(b):
ans += weight
union(a, b)
print(ans)
if __name__ == '__main__':
solution()
풀이 해설
문제 이름부터 대놓고 MST 유형임을 홍보하고 있으므로, 크루스칼 알고리즘을 구현하면 된다.
관련 알고리즘 이론은 갓킹독의 강의를 참고하면 쉽게 이해할 수 있다.
크루스칼 알고리즘은 크게 세 가지 step으로 구성된다.
- 선택하지 않은 간선 중 가중치 낮은 순으로 간선 선택
- 1에서 선택한 간선으로 연결되는 두 정점이 서로 다른 그룹이면, 해당 간선을 최종 선택
- 최종 선택한 간선으로 연결되는 두 정점을 같은 그룹으로 union
집합의 표현 풀이 내용으로 대체한다.
caution
⚠️TC 입력받을 때 저장 순서 고려하기⚠️
for _ in range(E):
a, b, weight = list(map(int, input().split()))
tree.append((weight, a, b))
다음과 같이 입력 받은 순은 정점1
정점2
간선 가중치
순이지만,
크루스칼 알고리즘 구현을 위해 가중치 기준으로 오름차순 정렬하려면 간선 가중치를 0번 인덱스에 두는 것이 더 깔삼하다.
📌크루스칼 알고리즘
for data in tree:
weight, a, b = data
if find(a) != find(b):
ans += weight
union(a, b)
간선 가중치가 낮은 순으로 순회하며, 해당 간선과 연결된 두 정점이 같은 그룹에 속하는지 find
로 체크한다.
만약 같은 그룹이라면 해당 간선을 스패닝 트리에 포함시킬 수 없다. --> 사이클이 형성되기 때문
따라서 서로 다른 그룹일 경우에만 해당 간선의 가중치를 합산하고, 연결된 두 정점은 같은 그룹으로 union
처리한다.
그리고 마지막으로,
문제에서 스패닝 트리 형성이 보장된다고 하였기 때문에, 순회가 종료되면 무조건적으로 정답 값이 도출됨을 알 수 있다.
메모
- 그놈의
setrecursionlimit
또 까먹음
ㅜㅜ...