Advertisement
vkazar

Untitled

Dec 2nd, 2023
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 4.38 KB | None | 0 0
  1. package sprint6.tasks.K2
  2.  
  3. import java.io.BufferedReader
  4. import java.io.InputStreamReader
  5. import java.util.*
  6.  
  7. lateinit var vertexes: Array<MutableMap<Int, Int>>
  8. lateinit var matrix: Array<Array<Int>>
  9.  
  10. fun main() {
  11.     val buffer = BufferedReader(InputStreamReader(System.`in`))
  12.     val text = buffer.readText()
  13.     val tokenizer = StringTokenizer(text, " \n\r")
  14.     val vertexCount = tokenizer.nextToken().toInt()
  15.     val edgeCount = tokenizer.nextToken().toInt()
  16.     //Список смежности
  17.     vertexes = Array(vertexCount + 1) { mutableMapOf() }
  18.     //Матрица результатов
  19.     matrix = Array(vertexCount + 1) {
  20.         Array(vertexCount + 1) { Int.MAX_VALUE }
  21.     }
  22.  
  23.     //Заполнение списка смежности
  24.     repeat(edgeCount) {
  25.         //Считывание строки
  26.         val vertex = tokenizer.nextToken().toInt()
  27.         val toVertex = tokenizer.nextToken().toInt()
  28.         val size = tokenizer.nextToken().toInt()
  29.         //Получение веса ребра между вершинами
  30.         val curSize = vertexes[vertex][toVertex]
  31.         //Если оно не указано или его вес больше считанного -- запомнить
  32.         if (curSize == null || curSize > size) {
  33.             //Т.к. граф неориентированный, каждое ребро ведёт в 2 стороны. Ну или есть 2 ребра в каждую сторону с одинаковым весом
  34.             vertexes[vertex][toVertex] = size
  35.             vertexes[toVertex][vertex] = size
  36.         }
  37.     }
  38.     // Заполнение результата
  39.     matrix.indices.forEach { vertex ->
  40.         if (vertex == 0) return@forEach
  41.         //Расстояние рассчитывается построчно
  42.         //Т.е. для каждой строки применяется алгоритм Дейкстры
  43.         //Массив признаков посещённости
  44.         val visited = BooleanArray(vertexCount + 1) { false }
  45.         //Расстоянеи до текущей вершины равно нулю
  46.         matrix[vertex][vertex] = 0
  47.  
  48.         //Функция обновления расстояния
  49.         val relax: (Int, Int) -> Unit = { u, v ->
  50.             val potential = matrix[vertex][u] + vertexes[v][u]!!
  51.             val cur = matrix[vertex][v]
  52.             if (cur > potential) {
  53.                 matrix[vertex][v] = potential
  54.                 matrix[v][vertex] = potential
  55.             }
  56.         }
  57.  
  58.         while (true) {
  59.             // вершина на минимальном расстоянии от текущей. Если такой нет -- выход
  60.             val minDistVertex = getMinDistNotVisited(vertex, visited) ?: break
  61.             //Если ближайшая в бесконечности (нет пути), то выход
  62.             if (matrix[vertex][minDistVertex] == Int.MAX_VALUE) break
  63.  
  64.             visited[minDistVertex] = true
  65.             //Соседи текущей обрабатываемой вершины
  66.             val neighbours = vertexes[minDistVertex].keys
  67.                 //Т.к. граф неориентированный, то матрица симметрична относительно главной диаогнали
  68.                 //А значит все вершины слева от нулевой длины уже обновлены в минимум в прошлых итерациях построчного перебора матрицы
  69.                 .filter { it > vertex }
  70.             for (n in neighbours) {
  71.                 relax(minDistVertex, n)
  72.             }
  73.         }
  74.     }
  75.  
  76.     //формирование ответа
  77.     buildString {
  78.         for (i in 1..vertexCount) {
  79.             for (j in 1..vertexCount)
  80.                  append("${matrix[i][j].let { if (it != Int.MAX_VALUE) it else -1 }} ")
  81.            appendLine()
  82.         }
  83.     }.let(::print)
  84. }
  85.  
  86. fun getMinDistNotVisited(forVertex: Int, visited: BooleanArray): Int? {
  87.     var currentMinimum = Int.MAX_VALUE
  88.     var currentMinimumVertex: Int? = null
  89.  
  90.     for (v in 1..vertexes.lastIndex) {
  91.         if (!visited[v] && matrix[forVertex][v] < currentMinimum) {
  92.             currentMinimum = matrix[forVertex][v]
  93.             currentMinimumVertex = v
  94.         }
  95.     }
  96.     return currentMinimumVertex
  97. }
  98.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement