문제 정보
- 문제 출처: 백준 온라인 저지
- 문제 링크: 1197 최소 스패닝 트리
- 제출 언어: Swift
- 알고리즘 분류:
- 그래프 이론
- 최소 스패닝 트리
풀이
최소 스패닝 트리
- 그래프 내의 모든 node들을 최소의 간선 비용으로 연결하는 트리이다
- cycle이 없는 조건일 경우 사용한다
- Greedy를 이용한 그래프 탐색 알고리즘이다
- Kruskal알고리즘과 Prim알고리즘 이 두 알고리즘으로 해결할 수 있다
Kruskal's Alg
- 1) 그래프 내의 모든 edge(간선)들을 비용에 따라 오름차순으로 정렬한다
- 2) 1)에서의 edge들을 최소 스패닝 트리에 추가한다
- 3) cycle을 형성하는 edge는 건너뛴다
Prim's Alg
- 1) 임의의 node를 시작 node로 설정
- 2) 각 node마다 최소 스패닝 트리가 될 수 있는 최소 비용 값과 연결 정보를 가진다
- 3) 가장 작은 최소 비용 값을 갖는 node에 방문한다
- 4) 방문한 node의 인접 node들의 최소 비용 값과 연결 정보를 갱신한다
- 최소 스패닝 트리가 cycle없이 모든 node를 연결할 때까지 3) ~ 4)를 반복한다
알고리즘 적용
Prim's Alg와 유사한 DIJKSTRA 알고리즘을 최근에 풀었기 때문에 Kruskal's Alg를 이용하여 풀었다
모든 Node들이 자신의 parent값을 나타내는 배열을 생성하여 자기 node의 값들을 넣어준다
이 후 모든 간선들을 돌면서 root(가장 상위 parent)값들이 같지 않은 tree들을 합치고 최소 비용에 더해준다
두 개의 tree를 합칠 경우 둘 중 더 작은 값을 가진 node가 상위 tree가 되도록 한다
-> 일정한 규칙을 정해져서 시간을 단축시킨 것 이므로 큰 값을 가진 tree가 상위 tree가 되어도 상관 없음
func find(_ target: Int)-> Int
: 해당 target값을 가진 Node의 root값 반환- 해당 target값의 parent가 target값과 같을 경우) 초기화해준 상태 그대로이므로, 가장 root node임을 알 수 있다.
- -> 자기 자신의 값 target 반환
- 그렇지 않을 경우) root node를 찾을 때까지 recursive 함수를 통해 계속 parent node에 접근한다
-
parent[target] = find(parent[target]) 로 경로를 압축하지 않으면 시간복잡도가 커지는 것 주의!
func union(_ a: Int, _ b :Int)
: 두 개의 값을 가진 Node를 하나의 tree로 합친다- 줄줄이 일 자로 node가 연결되는 것을 막기 위해 특정한 기준(a<b)를 세워서 두 tree를 합침
전체 코드
import Foundation
func find(_ target: Int)-> Int{
if parent[target] == target{
return target
}else{
parent[target] = find(parent[target])
return parent[target]
}
}
func union(_ a: Int, _ b :Int){
if a < b{
parent[find(b)] = a
}else{
parent[find(a)] = b
}
}
let n = readLine()!.split(separator: " ").map{Int(String($0))!}
let (V,E) = (n[0], n[1])
var weight: Int = 0
var edge: [[Int]] = Array()
var parent: [Int] = Array(0...V)
for i in 0..<E{
edge.append(readLine()!.split(separator: " ").map{Int(String($0))!})
}
for e in edge.sorted(by: {$0[2] < $1[2]}){
let (u,v) = (e[0], e[1])
if find(u) != find(v){
union(u,v)
weight += e[2]
}
}
print(weight)
'Algorithm > 문제풀이' 카테고리의 다른 글
[백준/Swift] 1789 수들의 합 (0) | 2023.05.09 |
---|---|
[백준/Swift] 2252 줄 세우기 (0) | 2023.05.09 |
[백준/Swift] 1916 최소비용 구하기 (0) | 2023.05.09 |
[백준/Swift] 1806 부분합 (1) | 2023.05.09 |
[백준/Swift] 1700 멀티탭 스케줄링 (2) | 2023.05.02 |