Программа курса:
Разбор задачи: Нахождение возможных безопасных состояний
Предложенный нами код:
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],[],[]]
Шаги алгоритма:
- Узел
0:- Ребра:
1, 2. - Переходим к узлу
1.- Узел
1ведет к2и3. - Узел
3ведет к0(цикл). Узел1— не безопасен.
- Узел
- Узел
2ведет к5. Узел5безопасен, значит, узел2— безопасен. - Узел
0— безопасен.
- Ребра:
- Аналогично проверяются остальные узлы.
Результат:
[2, 4, 5, 6]
Преимущества решения
- Простая структура на основе DFS.
- Использование массива
visitedдля предотвращения повторных вычислений. - Лаконичное добавление безопасных узлов в список.
Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии