https://www.acmicpc.net/problem/1613
1613번: 역사
첫째 줄에 첫 줄에 사건의 개수 n(400 이하의 자연수)과 알고 있는 사건의 전후 관계의 개수 k(50,000 이하의 자연수)가 주어진다. 다음 k줄에는 전후 관계를 알고 있는 두 사건의 번호가 주어진다.
www.acmicpc.net
난이도 : 골드 3
태그 : 그래프 이론, 플로이드-워셜
1. 설명
플로이드 워셜 알고리즘을 응용하여 풀 수 있을 것 같습니다.
플로이드 워셜 알고리즘을 잘 모르겠다면, 아래 포스팅을 참고해주세요.
https://uknowblog.tistory.com/39
[백준 11404번][Kotlin] 플로이드
https://www.acmicpc.net/problem/11404 11404번: 플로이드 첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다.
uknowblog.tistory.com
플로이드 워셜 알고리즘은 최단경로를 구하는 알고리즘이지만,
순서를 구할 때에도 응용할 수 있습니다.
2. 소스코드
<kotlin />
import java.util.*
fun main() = with(System.`in`.bufferedReader()) {
val (n, k) = readLine().split(" ").map { it.toInt() }
val arr = Array(n + 1) { Array(n + 1) { 987654321 } }
repeat(k) {
val st = StringTokenizer(readLine())
val from = st.nextToken().toInt()
val to = st.nextToken().toInt()
arr[from][to] = 1
}
for (k in 1..n) {
for (i in 1..n) {
for (j in 1..n) {
if (arr[i][j] > arr[i][k] + arr[k][j]) {
arr[i][j] = arr[i][k] + arr[k][j]
}
}
}
}
val sb = StringBuilder()
repeat(readLine().toInt()) {
val st = StringTokenizer(readLine())
val from = st.nextToken().toInt()
val to = st.nextToken().toInt()
if (arr[from][to] == arr[to][from]) sb.append("0")
else if (arr[from][to] > arr[to][from]) sb.append("1")
else sb.append("-1")
sb.append("\n")
}
print(sb)
}
일반적인 플로이드 워셜 알고리즘과 같으나,
a와 b의 순서관계가 주어진다면 arr[a][b]를 1로 만들어줍니다.
이후, 플로이드 워셜 알고리즘을 적용시키고,
플로이드 워셜이 끝나면
arr[a][b]와 arr[b][a]의 값을 비교합니다.
arr[a][b]가 arr[b][a]보다 크다면, b의 사건이 먼저 일어난 것입니다. 따라서 1을,
arr[b][a]가 arr[a][b]보다 크다면, a의 사건이 먼저 일어난 것이므로 -1을,
arr[a][b]와 arr[b][a]가 같다면 순서를 가릴 수 없으므로 0을 출력합니다.
3. 후기
그래프는 언제 해도 재밌습니다.
'코딩테스트 > Kotlin' 카테고리의 다른 글
[백준 1325번] [Kotlin] 효율적인 해킹 (0) | 2023.04.16 |
---|---|
[백준 1380번] [Kotlin] 귀걸이 (0) | 2023.04.16 |
[백준 2294번] [Kotlin] 동전 2 (0) | 2023.04.01 |
[백준 10102번] [Kotlin] 개표 (0) | 2023.03.31 |
[백준 2557번] [Kotlin] Hello World (0) | 2023.03.31 |