Разбор задачи: Нахождение возможных безопасных состояний

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

 def eventualSafeNodes(graph):
        def explore(i):
            visited[i] = 0
            for v in graph[i]:
                if visited[v] == 0 or (visited[v] == -1 and explore(v)): return True
            visited[i] = 1
            res.append(i)
            return False
        visited, res = [-1] * len(graph), []
        for i in range(len(graph)):
            if visited[i] == -1: explore(i)
        return sorted(res)

Данный алгоритм использует DFS (глубину поиска) для определения безопасных узлов. Рассмотрим его шаги и ключевые фрагменты.


1. Инициализация переменных

visited, res = [-1] * len(graph), []
  • visited — массив для отслеживания состояния каждого узла:
    • -1 означает, что узел не посещен.
    • 0 означает, что узел в процессе проверки (то есть, мы находимся в нем в текущем стеке рекурсии).
    • 1 означает, что узел безопасен.
  • res — список для хранения индексов безопасных узлов.

2. Функция explore(i)

Эта функция используется для рекурсивного обхода графа. Ее задача — определить, является ли текущий узел безопасным.

Входные параметры

  • i — индекс текущего узла.

Реализация:

visited[i] = 0
  • Помечаем текущий узел как "в процессе проверки".
for v in graph[i]:
    if visited[v] == 0 or (visited[v] == -1 and explore(v)):
        return True
  • Проходим по всем узлам, к которым ведут ребра из текущего узла.
    • Если один из соседей уже находится "в процессе проверки" (visited[v] == 0), это значит, что мы нашли цикл, и узел не является безопасным.
    • Если соседний узел еще не был посещен (visited[v] == -1), вызываем explore(v) для проверки его безопасности. Если он не безопасен, возвращаем True.
visited[i] = 1
res.append(i)
return False
  • Если все соседи безопасны, помечаем текущий узел как безопасный (visited[i] = 1) и добавляем его в список безопасных узлов res.

3. Основной цикл

for i in range(len(graph)):
    if visited[i] == -1:
        explore(i)
  • Обходим все узлы графа.
  • Если узел еще не посещен (visited[i] == -1), проверяем его безопасность с помощью функции explore.

4. Сортировка результата

return sorted(res)
  • Возвращаем отсортированный список безопасных узлов.

Пример работы

Входные данные:

graph = [[1,2],[2,3],[5],[0],[5],[],[]]

Шаги алгоритма:

  1. Узел 0:
    • Ребра: 1, 2.
    • Переходим к узлу 1.
      • Узел 1 ведет к 2 и 3.
      • Узел 3 ведет к 0 (цикл). Узел 1 — не безопасен.
    • Узел 2 ведет к 5. Узел 5 безопасен, значит, узел 2 — безопасен.
    • Узел 0 — безопасен.
  2. Аналогично проверяются остальные узлы.

Результат:

[2, 4, 5, 6]

Преимущества решения

  1. Простая структура на основе DFS.
  2. Использование массива visited для предотвращения повторных вычислений.
  3. Лаконичное добавление безопасных узлов в список.

 



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