Решение задачи #13. Python Яндекс CodeRun, Путь в графе

Опубликовано: 22.02.2025, 21:32 | Автор: hdhAI

Вариант решения задачи на языке программирования Python с Яндекс CodeRun.
Название задачи:
Статус решения: "Решено".

Условие задачи:
В неориентированном графе требуется найти минимальный путь между двумя вершинами.

Формат ввода:
Первым на вход поступает число N – количество вершин в графе (1 ≤≤ N ≤≤ 100). Затем записана матрица смежности (0 обозначает отсутствие ребра, 1 – наличие ребра). Далее задаются номера двух вершин – начальной и конечной.

Формат вывода:
Выведите сначала L – длину кратчайшего пути (количество ребер, которые нужно пройти), а потом сам путь. Если путь имеет длину 0, то его выводить не нужно, достаточно вывести длину. Необходимо вывести путь (номера всех вершин в правильном порядке). Если пути нет, нужно вывести -1.

Решение:


Python
import sys
from collections import deque

def main():
    # Чтение входных данных
    N = int(input())  # Количество вершин в графе
    graph = [list(map(int, input().split())) for _ in range(N)]  # Матрица смежности графа
    start, end = map(int, input().split())  # Начальная и конечная вершины (нумерация с 1)

    # Если начальная и конечная вершины совпадают
    if start == end:
        print(0)  # Путь имеет длину 0
        return

    # Преобразуем нумерацию вершин с 1..N на 0..N-1 для удобства работы
    start -= 1
    end -= 1

    # Обход в ширину (BFS) для поиска кратчайшего пути
    queue = deque([start])  # Очередь для BFS
    visited = [-1] * N  # Массив расстояний до вершин (-1 означает "не посещена")
    parent = [-1] * N  # Массив для восстановления пути
    visited[start] = 0  # Расстояние до начальной вершины равно 0

    while queue:
        current = queue.popleft()  # Извлекаем текущую вершину из очереди
        for neighbor in range(N):  # Перебираем всех соседей текущей вершины
            if graph[current][neighbor] == 1 and visited[neighbor] == -1:  # Если есть ребро и сосед не посещён
                visited[neighbor] = visited[current] + 1  # Обновляем расстояние
                parent[neighbor] = current  # Запоминаем предка
                queue.append(neighbor)  # Добавляем соседа в очередь

    # Если конечная вершина недостижима
    if visited[end] == -1:
        print(-1)
        return

    # Восстановление пути
    path = []
    current = end
    while current != -1:  # Идём от конечной вершины к начальной через массив parent
        path.append(current + 1)  # Преобразуем обратно к нумерации с 1
        current = parent[current]
    path.reverse()  # Переворачиваем путь, чтобы он шёл от начальной к конечной вершине

    # Вывод результата
    print(visited[end])  # Длина пути
    if visited[end] > 0:  # Если длина пути больше 0, выводим сам путь
        print(*path)


if __name__ == '__main__':
    main()
	

Объяснение кода


1. Чтение входных данных

Мы считываем количество вершин N и матрицу смежности графа.
Матрица смежности — это двумерный массив размером N×N, где элемент graph[i][j] равен 1, если между вершинами i и j есть ребро, и 0, если нет.
Также считываем номера начальной (start) и конечной (end) вершин.

2. Обработка случая, когда начальная и конечная вершины совпадают
Если start == end, то путь имеет длину 0, и его не нужно выводить. Просто выводим 0.

3. Преобразование нумерации вершин
Для удобства работы преобразуем нумерацию вершин с 1..N на 0..N-1.

4. Поиск кратчайшего пути с помощью BFS
Мы используем алгоритм обхода в ширину (BFS), который гарантирует нахождение кратчайшего пути в невзвешенном графе.
Создаём очередь queue для хранения вершин, которые нужно обработать.
Создаём массив visited, где visited[i] хранит расстояние от начальной вершины до вершины i. Изначально все значения равны -1 (вершины не посещены).
Создаём массив parent, где parent[i] хранит предка вершины i для восстановления пути.

5. Обход графа
Пока очередь не пуста:
Извлекаем текущую вершину из очереди.
Перебираем всех её соседей. Если сосед ещё не посещён, обновляем его расстояние, запоминаем предка и добавляем его в очередь.

6. Проверка достижимости конечной вершины
Если visited[end] == -1, это означает, что конечная вершина недостижима. В этом случае выводим -1.

7. Восстановление пути
Если конечная вершина достижима, восстанавливаем путь, двигаясь от конечной вершины к начальной через массив parent.
Преобразуем нумерацию обратно к 1..N и переворачиваем путь, чтобы он шёл от начальной к конечной вершине.

8. Вывод результата
Выводим длину пути (visited[end]).
Если длина пути больше 0, выводим сам путь.

Пример работы программы:
Ввод:
5
0 1 0 0 1
1 0 1 0 0
0 1 0 1 0
0 0 1 0 1
1 0 0 1 0
1 5

Вывод:
2
1 2 3 4 5

Объяснение:
Граф содержит путь из вершины 1 в вершину 5 через вершины 2, 3 и 4.
Длина пути равна 4.

Пример без пути:
Ввод:
4
0 1 0 0
1 0 0 0
0 0 0 1
0 0 1 0
1 4

Вывод:
-1

Объяснение:
Вершина 1 и вершина 4 находятся в разных компонентах связности, поэтому путь между ними отсутствует.

Детали реализации:
Сложность алгоритма :
Временная сложность: O(N2), так как мы используем матрицу смежности.
Пространственная сложность: O(N2) для хранения матрицы смежности и O(N) для массивов visited и parent.

Ограничения:
Код работает корректно при N≤100, что соответствует ограничениям задачи.
Алгоритм укладывается в ограничения по времени и памяти.

Обработка граничных случаев:
Если начальная и конечная вершины совпадают, программа выведет 0.
Если пути нет, программа выведет -1.

Источник решения: hdhai.com

Похожие статьи
Интересное





Warning: file_put_contents(/var/www/angella1/data/www/hdhai.com/counter/count.php): Failed to open stream: Permission denied in /var/www/angella1/data/www/hdhai.com/counter.php on line 89