MST를 통해 주어진 기준에 따라 가장 높은 이득을 얻어내는 값을 구한다. 이때 모든 경우를 탐색하는 게 아니라 이분 탐색을 통해 탐색 경우를 줄일 수 있다.
(간선 복구 비용) + (간선 복구 시간 * gain)
기준으로 정렬한다. 오름차순 정렬을 통해 최소 비용 간선부터 꺼내올 수 있다.import Foundation
let input = readLine()!.split(separator: " ").map{Int(String($0))!}
let (N, M, F) = (input[0], input[1], input[2])
var edges = [(Int, Int, Int, Int)]()
for _ in 0..<M {
let edge = readLine()!.split(separator: " ").map{Int(String($0))!}
edges.append((edge[0], edge[1], edge[2], edge[3]))
}
var left = 0.0
var right = Double(F)
func find(node:Int) -> Int {
if parents[node] == node {
return node
} else {
parents[node] = find(node:parents[node])
return parents[node]
}
}
func union(node1:Int, node2:Int) -> Bool {
let root1 = find(node: node1)
let root2 = find(node: node2)
if root1 == root2 {
return false
} else {
parents[root2] = root1
return true
}
}
func Kruskal(mid:Double) -> Bool {
func edgeSort(num1: (Int, Int, Int, Int), num2: (Int, Int, Int, Int)) -> Bool {
return (Double(num1.2) + Double(num1.3) * mid) < (Double(num2.2) + Double(num2.3) * mid)
}
edges.sort(by: edgeSort)
var total = 0.0
var edgeCnt = 0
for edge in edges {
let node1 = edge.0
let node2 = edge.1
let cost = edge.2
let time = edge.3
if union(node1: node1, node2: node2) == true {
total += (Double(cost) + Double(time) * mid)
edgeCnt += 1
if edgeCnt == N-1 {
break
}
}
}
if total <= Double(F) {
return true
} else {
return false
}
}
var parents = Array(repeating: 0, count: N+1)
var mid = 0.0
for _ in 0..<100 {
for i in 0..<N+1 {
parents[i] = i
}
mid = (left + right) / 2
if Kruskal(mid:mid) == true {
left = mid
} else {
right = mid
}
}
if mid < 0 {
print("0.0000")
} else {
let midString = String(format: "%.4f", mid)
print(midString)
}