티스토리 뷰
문제 링크
문제
황선자씨는 우주신과 교감을 할수 있는 채널러 이다. 하지만 우주신은 하나만 있는 것이 아니기때문에 황선자 씨는 매번 여럿의 우주신과 교감하느라 힘이 든다. 이러던 와중에 새로운 우주신들이 황선자씨를 이용하게 되었다.
하지만 위대한 우주신들은 바로 황선자씨와 연결될 필요가 없다. 이미 황선자씨와 혹은 이미 우주신끼리 교감할 수 있는 우주신들이 있기 때문에 새로운 우주신들은 그 우주신들을 거쳐서 황선자 씨와 교감을 할 수 있다.
우주신들과의 교감은 우주신들과 황선자씨 혹은 우주신들 끼리 이어진 정신적인 통로를 통해 이루어 진다. 하지만 우주신들과 교감하는 것은 힘든 일이기 때문에 황선자씨는 이런 통로들이 긴 것을 좋아하지 않는다. 왜냐하면 통로들이 길 수록 더 힘이 들기 때문이다.
또한 우리들은 3차원 좌표계로 나타낼 수 있는 세상에 살고 있지만 우주신들과 황선자씨는 2차원 좌표계로 나타낼 수 있는 세상에 살고 있다. 통로들의 길이는 2차원 좌표계상의 거리와 같다.
이미 황선자씨와 연결된, 혹은 우주신들과 연결된 통로들이 존재한다. 우리는 황선자 씨를 도와 아직 연결이 되지 않은 우주신들을 연결해 드려야 한다. 새로 만들어야 할 정신적인 통로의 길이들이 합이 최소가 되게 통로를 만들어 “빵상”을 외칠수 있게 도와주자.
입력
첫째 줄에 우주신들의 개수(N<=1,000) 이미 연결된 신들과의 통로의 개수(M<=1,000)가 주어진다.
두 번째 줄부터 N개의 줄에는 황선자를 포함하여 우주신들의 좌표가 (0<= X<=1,000,000), (0<=Y<=1,000,000)가 주어진다. 그 밑으로 M개의 줄에는 이미 연결된 통로가 주어진다. 번호는 위의 입력받은 좌표들의 순서라고 생각하면 된다. 좌표는 정수이다.
출력
첫째 줄에 만들어야 할 최소의 통로 길이를 출력하라. 출력은 소수점 둘째짜리까지 출력하여라.
문제 풀이
이 문제는 제목 부터 이상하더니 내용에는 "빵상"이라는 키워드가 나와서 웃겼던 문제였어욬ㅋㅋㅋㅋ
어쨌든 문제풀이를 시작해보면...
최소 스패닝 트리를 사용하는 문제입니다.
하지만 특이한 점은 미리 정해진 경로가 존재한다는 것이죠.
사실 풀이는 아주 간단합니다.
미리 정해진 경로는 선택되었다고 설정한 뒤 남은 경로로 최소 스패닝 트리를 만들어 주시면 됩니다.
이 때 미리 정해진 경로의 길이는 결과에 영향을 주지 않기 때문에 그냥 연결만 해주시면 됐어요!
저는 크루스칼 알고리즘을 사용해서 최소 스패닝 트리를 만들어줬습니다!
그리고 이 문제는 반올림을 하니까 결과가 다르게 나와서 그냥 결과에서 소수점을 2자리까지만 출력하도록 코딩해야했던게 주의할 점?? 이라고 생각합니다.
소스 코드
import Foundation
func solution(){
let firstLine = readLine()!.split(separator: " ").map({Int(String($0))!})
let n = firstLine[0]
let m = firstLine[1]
var parent = Array(0...n)
var lines: Int = 0
var result: Double = 0
var edges: [[Double]] = [[0,0]]
var distanceData: [(Int,Int,Double)] = []
func find(_ index: Int) -> Int {
if parent[index] == index {
return index
} else {
parent[index] = find(parent[index])
return parent[index]
}
}
func union(_ a: Int, _ b: Int){
let p1 = find(a)
let p2 = find(b)
if p1 < p2 {
parent[p2] = p1
} else {
parent[p1] = p2
}
}
for _ in 0..<n{
let data = readLine()!.split(separator: " ").map({Double(String($0))!})
edges.append(data)
}
// 미리 연결된 것들을 미리 처리한다.
for _ in 0..<m{
let data = readLine()!.split(separator: " ").map({Int(String($0))!})
lines += 1
union(data[0],data[1])
}
// 점들간의 거리를 구한다
for i in 1..<edges.count{
for j in i+1..<edges.count{
let distance = sqrt(pow(edges[i][0] - edges[j][0], 2) + pow(edges[i][1] - edges[j][1], 2))
distanceData.append((i,j,distance))
}
}
// 정렬
distanceData.sort { (a, b) -> Bool in
return a.2 < b.2
}
// 크루스칼 알고리즘 수행
for i in 0..<distanceData.count{
if lines == n-1{
break
}
if find(distanceData[i].0) != find(distanceData[i].1){
result += distanceData[i].2
lines += 1
union(distanceData[i].0, distanceData[i].1)
}
}
print(String(format: "%.2f", result))
}
solution()
'Algorithm > BaekJoon' 카테고리의 다른 글
[백준] 1904번 01타일 [Swift] (0) | 2020.10.06 |
---|---|
[백준] 2887번 행성 터널 [Swift] (0) | 2020.09.27 |
[백준] 4386번 별자리 만들기 [Swift] (0) | 2020.09.26 |
[백준] 1197번 최소 스패닝 트리 [Swift] (0) | 2020.09.26 |
[백준] 9372번 상근이의 여행 [Swift] (0) | 2020.09.25 |
- Total
- Today
- Yesterday
- document
- 알고리즘
- pattern
- 자료구조
- operator
- OSTEP
- 동시성
- dfs
- 테이블뷰
- Apple
- OS
- Swift
- DP
- 백준
- IOS
- Xcode
- 스위프트
- 코테
- 코딩테스트
- 문법
- BFS
- 앱개발
- Combine
- operating
- System
- 아이폰
- design
- Publisher
- 프로그래밍
- mac
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |