Skip to content

Commit bbc7781

Browse files
committed
[Gold II] Title: 네트워크 복구, Time: 308 ms, Memory: 78580 KB -BaekjoonHub
1 parent 1bcfe9b commit bbc7781

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# [Gold II] 네트워크 복구 - 2211
2+
3+
[문제 링크](https://www.acmicpc.net/problem/2211)
4+
5+
### 성능 요약
6+
7+
메모리: 78580 KB, 시간: 308 ms
8+
9+
### 분류
10+
11+
그래프 이론, 최단 경로, 데이크스트라
12+
13+
### 제출 일자
14+
15+
2025년 11월 13일 19:50:36
16+
17+
### 문제 설명
18+
19+
<p>N(1 ≤ N ≤ 1,000)개의 컴퓨터로 구성된 네트워크가 있다. 이들 중 몇 개의 컴퓨터들은 서로 네트워크 연결이 되어 있어 서로 다른 두 컴퓨터 간 통신이 가능하도록 되어 있다. 통신을 할 때에는 서로 직접 연결되어 있는 회선을 이용할 수도 있으며, 회선과 다른 컴퓨터를 거쳐서 통신을 할 수도 있다.</p>
20+
21+
<p>각 컴퓨터들과 회선은 그 성능이 차이가 날 수 있다. 따라서 각각의 직접 연결되어 있는 회선을 이용해서 통신을 하는데 걸리는 시간이 서로 다를 수 있다. 심지어는 직접 연결되어 있는 회선이 오히려 더 느려서, 다른 컴퓨터를 통해서 통신을 하는 것이 더 유리할 수도 있다. 직접 연결되어 있는 회선을 사용할 경우에는 그 회선을 이용해서 통신을 하는 데 드는 시간만큼이 들게 된다. 여러 개의 회선을 거치는 경우에는 각 회선을 이용해서 통신을 하는 데 드는 시간의 합만큼의 시간이 걸리게 된다.</p>
22+
23+
<p>어느 날, 해커가 네트워크에 침입하였다. 네트워크의 관리자는 우선 모든 회선과 컴퓨터를 차단한 후, 해커의 공격을 막을 수 있었다. 관리자는 컴퓨터에 보안 시스템을 설치하려 하였는데, 버전 문제로 보안 시스템을 한 대의 슈퍼컴퓨터에만 설치할 수 있었다. 한 컴퓨터가 공격을 받게 되면, 네트워크를 통해 슈퍼컴퓨터에 이 사실이 전달이 되고, 그러면 슈퍼컴퓨터에서는 네트워크를 이용해서 보안 패킷을 전송하는 방식을 사용하기로 하였다. 준비를 마친 뒤, 관리자는 다시 네트워크를 복구하기로 하였다. 이때, 다음의 조건들이 만족되어야 한다.</p>
24+
25+
<ol>
26+
<li>해커가 다시 공격을 할 우려가 있기 때문에, 최소 개수의 회선만을 복구해야 한다. 물론, 그렇다면 아무 회선도 복구하지 않으면 되겠지만, 이럴 경우 네트워크의 사용에 지장이 생기게 된다. 따라서 네트워크를 복구한 후에 서로 다른 두 컴퓨터 간에 통신이 가능하도록 복구해야 한다.</li>
27+
<li>네트워크를 복구해서 통신이 가능하도록 만드는 것도 중요하지만, 해커에게 공격을 받았을 때 보안 패킷을 전송하는 데 걸리는 시간도 중요한 문제가 된다. 따라서 슈퍼컴퓨터가 다른 컴퓨터들과 통신하는데 걸리는 최소 시간이, 원래의 네트워크에서 통신하는데 걸리는 최소 시간보다 커져서는 안 된다.</li>
28+
</ol>
29+
30+
<p>원래의 네트워크에 대한 정보가 주어졌을 때, 위의 조건을 만족하면서 네트워크를 복구하는 방법을 알아내는 프로그램을 작성하시오.</p>
31+
32+
### 입력
33+
34+
<p>첫째 줄에 두 정수 N, M이 주어진다. 다음 M개의 줄에는 회선의 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 컴퓨터와 B번 컴퓨터가 통신 시간이 C (1 ≤ C ≤ 10)인 회선으로 연결되어 있다는 의미이다. 컴퓨터들의 번호는 1부터 N까지의 정수이며, 1번 컴퓨터는 보안 시스템을 설치할 슈퍼컴퓨터이다. 모든 통신은 완전쌍방향 방식으로 이루어지기 때문에, 한 회선으로 연결된 두 컴퓨터는 어느 방향으로도 통신할 수 있다.</p>
35+
36+
### 출력
37+
38+
<p>첫째 줄에 복구할 회선의 개수 K를 출력한다. 다음 K개의 줄에는 복구한 회선을 나타내는 두 정수 A, B를 출력한다. 이는 A번 컴퓨터와 B번 컴퓨터를 연결하던 회선을 복구한다는 의미이다. 출력은 임의의 순서대로 하며, 답이 여러 개 존재하는 경우에는 아무 것이나 하나만 출력하면 된다.</p>
39+
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
let inf = 987654321
2+
let nm = readLine()!.split { $0 == " " }.map { Int(String($0))! },
3+
n = nm[0],
4+
m = nm[1]
5+
var graph = [[Edge]](repeating: [Edge](), count: n + 1)
6+
7+
for _ in 0..<m {
8+
let abc = readLine()!.split { $0 == " " }.map { Int(String($0))! },
9+
a = abc[0],
10+
b = abc[1],
11+
c = abc[2]
12+
graph[a].append(Edge(to: b, cost: c))
13+
graph[b].append(Edge(to: a, cost: c))
14+
}
15+
16+
17+
func djst(_ start: Int) -> [[Int]] {
18+
var dist = [Int](repeating: inf, count: n+1)
19+
var parent = [Int](repeating: -1, count: n + 1)
20+
var repairEdge = [[Int]]()
21+
var heap = Heap<(Int, Int)>(sort: { $0.1 < $1.1 })
22+
heap.insert((start, 0))
23+
24+
while !heap.isEmpty {
25+
let (currentNode, currentCost) = heap.pop()!
26+
27+
if currentCost > dist[currentNode] { continue }
28+
29+
for edge in graph[currentNode] {
30+
let nextCost = currentCost + edge.cost
31+
32+
if dist[edge.to] > nextCost {
33+
// 어떤 노드로부터 진입해야 이 노드로 올 때 최소인지 기록
34+
parent[edge.to] = currentNode
35+
dist[edge.to] = nextCost
36+
heap.insert((edge.to, nextCost))
37+
}
38+
}
39+
}
40+
for i in 2...n {
41+
if parent[i] != -1 {
42+
repairEdge.append([i, parent[i]])
43+
}
44+
}
45+
return repairEdge
46+
}
47+
48+
let edges = djst(1)
49+
50+
print(edges.count)
51+
for edge in edges {
52+
print(edge[0], edge[1])
53+
}
54+
55+
56+
struct Edge {
57+
let to: Int
58+
let cost: Int
59+
}
60+
61+
struct Heap<T> {
62+
private var elements: [T]
63+
private let priority: (T, T) -> Bool
64+
65+
init(sort: @escaping (T, T) -> Bool) {
66+
self.elements = []
67+
self.priority = sort
68+
}
69+
70+
var isEmpty: Bool { elements.isEmpty }
71+
72+
mutating func insert(_ value: T) {
73+
elements.append(value)
74+
siftUp(from: elements.count - 1)
75+
}
76+
77+
mutating func pop() -> T? {
78+
guard !elements.isEmpty else { return nil }
79+
elements.swapAt(0, elements.count - 1)
80+
let value = elements.removeLast()
81+
siftDown(from: 0)
82+
return value
83+
}
84+
85+
private mutating func siftUp(from index: Int) {
86+
var child = index
87+
var parent = (child - 1) / 2
88+
while child > 0 && priority(elements[child], elements[parent]) {
89+
elements.swapAt(child, parent)
90+
child = parent
91+
parent = (child - 1) / 2
92+
}
93+
}
94+
95+
private mutating func siftDown(from index: Int) {
96+
var parent = index
97+
while true {
98+
let left = 2 * parent + 1
99+
let right = 2 * parent + 2
100+
var candidate = parent
101+
102+
if left < elements.count && priority(elements[left], elements[candidate]) {
103+
candidate = left
104+
}
105+
if right < elements.count && priority(elements[right], elements[candidate]) {
106+
candidate = right
107+
}
108+
if candidate == parent { break }
109+
elements.swapAt(parent, candidate)
110+
parent = candidate
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)