Разбор задачи: Задержка сигнала в сети

Предложенный нами код решения:

 from heapq import heappush, heappop
from collections import defaultdict

def network_delay_time(times, n, k):
    # Построение графа
    graph = defaultdict(list)
    for u, v, w in times:
        graph[u].append((v, w))
    
    # Инициализация структуры для хранения времени
    min_heap = [(0, k)]  # (время, узел)
    visited = {}
    
    while min_heap:
        time, node = heappop(min_heap)
        
        if node in visited:
            continue
        
        visited[node] = time
        
        for neighbor, weight in graph[node]:
            if neighbor not in visited:
                heappush(min_heap, (time + weight, neighbor))
    
    if len(visited) == n:
        return max(visited.values())
    
    return -1

Построение графа

Изначально из входного списка times создаётся граф, представленный как словарь смежностей. Каждый узел указывает на список соседей с указанием времени передачи сигнала.

graph = defaultdict(list)
for u, v, w in times:
    graph[u].append((v, w))

Пример: для times = [[2, 1, 1], [2, 3, 1], [3, 4, 1]] граф выглядит так:

Граф:
2 -> (1, 1), (3, 1)
3 -> (4, 1)

Схема графа:

   2
  / \
(1) (1)
 /     \
1       3
         \
         (1)
           \
            4

Здесь числа в скобках — время передачи сигнала.


Инициализация

min_heap = [(0, k)]  # (время, узел)
visited = {}

Очередь с приоритетом min_heap изначально содержит начальный узел k с временем 0. Словарь visited пуст, так как ни один узел ещё не обработан.

Пример для k = 2:

min_heap = [(0, 2)]  # Начинаем с узла 2
visited = {}

Обработка узлов

Алгоритм работает в цикле, извлекая узел с минимальным временем из min_heap.

Шаг 1: Извлечение начального узла

time, node = heappop(min_heap)
if node in visited:
    continue
visited[node] = time

Для первого шага:

Извлекаем: (0, 2)
Добавляем в visited: {2: 0}

Шаг 2: Обработка соседей узла 2

for neighbor, weight in graph[node]:
    if neighbor not in visited:
        heappush(min_heap, (time + weight, neighbor))

Соседи узла 2:

  • Узел 1 с временем 1.
  • Узел 3 с временем 1.

Очередь обновляется:

min_heap = [(1, 1), (1, 3)]

Визуализация пробега

На каждом шаге узлы извлекаются из очереди и обрабатываются. Визуализируем:

  1. Изначально:
min_heap: [(0, 2)]
visited: {}
  1. Шаг 1: обработка узла 2:
Извлечено: (0, 2)
Добавлено в visited: {2: 0}
min_heap: [(1, 1), (1, 3)]

Граф после обработки:

   2 [обработан]
  / \
(1) (1)
 /     \
1       3
         \
         (1)
           \
            4
  1. Шаг 2: обработка узла 1:
Извлечено: (1, 1)
Добавлено в visited: {2: 0, 1: 1}
min_heap: [(1, 3)]

Узел 1 не имеет соседей, изменений в очереди нет.

  1. Шаг 3: обработка узла 3:
Извлечено: (1, 3)
Добавлено в visited: {2: 0, 1: 1, 3: 1}
min_heap: [(2, 4)]

Граф:

   2 [обработан]
  / \
(1) (1)
 /     \
1       3 [обработан]
         \
         (1)
           \
            4
  1. Шаг 4: обработка узла 4:
Извлечено: (2, 4)
Добавлено в visited: {2: 0, 1: 1, 3: 1, 4: 2}
min_heap: []

Граф:

   2 [обработан]
  / \
(1) (1)
 /     \
1       3 [обработан]
         \
         (1)
           \
            4 [обработан]

Проверка достижимости

После завершения цикла проверяется, обработаны ли все узлы:

if len(visited) == n:
    return max(visited.values())
return -1

Пример:

  • Если visited = {2: 0, 1: 1, 3: 1, 4: 2} и n = 4, то результат: max(visited.values()) = 2.
  • Если visited = {1: 0, 2: 1} и n = 3, то возвращается -1.

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии