PS(Problem Solving)/BOJ

[백준/BOJ] 1507번: 궁금한 민호

JunsuKim 2022. 9. 3.

목차

728x90

문제

https://www.acmicpc.net/problem/1507

 

1507번: 궁금한 민호

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 각각의 도시 사이에 이동하는데 필요한 시간이 주어진다. A에서 B로 가는 시간과 B에서 A로 가는 시간은 같다. 또, A와 B...

www.acmicpc.net

해설

플로이드 와샬 알고리즘을 역으로 이용하여 문제를 해결할 수 있다.

플로이드 와샬 알고리즘을 생각해보자.

만약 1번 도로, 2번 도로, 3번 도로가 있을 때, 1 - 2, 2 -3번 간 도로가 있다면 1 - 3번 도로는 없어도 1 - 2 -3을 통해 갈 수 있다. 즉 map[1][3] == map[1][2] + map[2][3]이 되는 것이다.

따라서 이 문제에서는 map[1][2] + map[2][3] == map[1][3]이라면, 이 도로는 없어도 되는 도로가 되므로 0으로 저장해준다.

마지막에 남은 도로들의 합을 더한 후, 양방향 도로이므로 / 2를 하여 출력해주면 된다.

코드

import java.util.*

private lateinit var map: Array<IntArray>
private lateinit var road: Array<IntArray>

fun main() = with(System.`in`.bufferedReader()) {
    val n = readLine().toInt()
    map = Array(n + 1) { IntArray(n + 1) }
    road = Array(n + 1) { IntArray(n + 1) }

    for(i in 1 .. n) {
        val st = StringTokenizer(readLine())
        for(j in 1 .. n) {
            map[i][j] = st.nextToken().toInt()
            road[i][j] = map[i][j]
        }
    }

    if(!reverseFloyd(n)) println(-1)
    else {
        var ans = 0
        for (i in 1..n) {
            for (j in 1..n) {
                ans += road[i][j]
            }
        }

        ans /= 2
        println(ans)
    }
}

private fun reverseFloyd(n: Int): Boolean {
    for(k in 1 .. n) {
        for(i in 1 .. n) {
            for(j in 1 .. n) {
                if(i == k || j == k) continue

                if(map[i][j] > map[i][k] + map[k][j]) return false
                if(map[i][j] == map[i][k] + map[k][j]) road[i][j] = 0
            }
        }
    }

    return true
}
728x90

'PS(Problem Solving) > BOJ' 카테고리의 다른 글

[백준/BOJ] 2638번: 치즈  (0) 2022.09.04
[백준/BOJ] 2660번: 회장뽑기  (0) 2022.09.03
[백준/BOJ] 16197번: 두 동전  (0) 2022.09.02
[백준/BOJ] 1719번: 택배  (0) 2022.09.01
[백준/BOJ] 1185번: 유럽여행  (1) 2022.08.31

댓글