Advertisement
vkazar

Untitled

Dec 2nd, 2023
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 4.94 KB | None | 0 0
  1. package sprint6.tasks.K
  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.     // Заполнение результата
  40.     matrix.indices.forEach { vertex ->
  41.         if (vertex == 0) return@forEach
  42.         //Расстояние рассчитывается построчно
  43.         //Т.е. для каждой строки применяется алгоритм Дейкстры
  44.         //Массив признаков посещённости
  45.         val visited = BooleanArray(vertexCount + 1) { false }
  46.         //Расстоянеи до текущей вершины равно нулю
  47.         matrix[vertex][vertex] = 0
  48.         val heap = MyHeap<Int>(compareBy { matrix[vertex][it] })
  49.         heap.put(vertex)
  50.  
  51.         //Функция обновления расстояния
  52.         val relax: (Int, Int) -> Unit = { u, v ->
  53.             val potential = matrix[vertex][u] + vertexes[v][u]!!
  54.             val cur = matrix[vertex][v]
  55.             if (cur > potential) {
  56.                 matrix[vertex][v] = potential
  57.                 heap.put(v)
  58.             }
  59.         }
  60.  
  61.         while (heap.isNotEmpty()) {
  62.             // вершина на минимальном расстоянии от текущей. Если такой нет -- выход
  63.             val minDistVertex = heap.pop()
  64.             if (visited[minDistVertex]) continue
  65.             //Если ближайшая в бесконечности (нет пути), то выход
  66.             if (matrix[vertex][minDistVertex] == Int.MAX_VALUE) break
  67.  
  68.             visited[minDistVertex] = true
  69.             //Соседи текущей обрабатываемой вершины
  70.             val neighbours = vertexes[minDistVertex].keys
  71.  
  72.             for (n in neighbours) {
  73.                 relax(minDistVertex, n)
  74.             }
  75.         }
  76.     }
  77.  
  78.     //формирование ответа
  79.     buildString {
  80.         for (i in 1..vertexCount) {
  81.             for (j in 1..vertexCount)
  82.                 append("${matrix[i][j].let { if (it != Int.MAX_VALUE) it else -1 }} ")
  83.             appendLine()
  84.         }
  85.     }.let(::print)
  86. }
  87.  
  88. class MyHeap<T>(private val comparator: Comparator<T>) {
  89.     private val _heap: MutableList<T> = mutableListOf()
  90.     val heap: List<T>
  91.         get() = _heap
  92.  
  93.     fun isNotEmpty() = _heap.isNotEmpty()
  94.  
  95.     fun put(element: T) {
  96.         _heap.add(element)
  97.         siftUp(_heap.lastIndex)
  98.     }
  99.  
  100.     fun pop(): T {
  101.         if (_heap.isEmpty()) error("heap is empty")
  102.         _heap.swap(0, _heap.lastIndex)
  103.         return _heap.removeLast().also { siftDown(0) }
  104.     }
  105.  
  106.  
  107.     private fun siftDown(idx: Int) {
  108.         val left = idx * 2 + 1
  109.         val right = left + 1
  110.  
  111.         val toSwap = when {
  112.             left >= _heap.size -> return
  113.             right >= _heap.size || comparator.compare(_heap[right], _heap[left]) > 0 -> left
  114.             else -> right
  115.         }
  116.         if (comparator.compare(_heap[idx], _heap[toSwap]) < 0) return
  117.         _heap.swap(toSwap, idx)
  118.         siftDown(toSwap)
  119.     }
  120.  
  121.     private fun siftUp(idx: Int) {
  122.         if (idx == 0) return
  123.         val parent = (idx - 1) / 2
  124.         if (comparator.compare(_heap[parent], _heap[idx]) < 0) return
  125.         _heap.swap(parent, idx)
  126.         siftUp(parent)
  127.     }
  128.  
  129.     private fun MutableList<T>.swap(left: Int, right: Int) {
  130.         val tmp = this[left]
  131.         this[left] = this[right]
  132.         this[right] = tmp
  133.     }
  134. }
  135.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement