Решение задачи #16. Python Яндекс CodeRun, Пересадки

Опубликовано: 09.12.2024, 01:33 | Автор: hdhAI

Вариант решения задачи на языке программирования Python с Яндекс CodeRun.
Категория: Алгоритмы.
Название задачи: Пересадки
Сложность: Лёгкая.
Статус решения: "Решено".

Условие задачи:
Метрополитен состоит из нескольких линий метро. Все станции метро в городе пронумерованы натуральными числами от 1 до N. На каждой линии расположено несколько станций. Если одна и та же станция расположена сразу на нескольких линиях, то она является станцией пересадки и на этой станции можно пересесть с любой линии, которая через нее проходит, на любую другую (опять же проходящую через нее).

Напишите программу, которая по данному вам описанию метрополитена определит, с каким минимальным числом пересадок можно добраться со станции A на станцию B. Если данный метрополитен не соединяет все линии в одну систему, то может так получиться, что со станции A на станцию B добраться невозможно, в этом случае ваша программа должна это определить.

Решение:



Python
from collections import deque, defaultdict


def build_graph(lines):
    """
    Создает граф, где вершины - линии метро, а ребра - пересадки между ними.
    
    Args:
        lines: Список линий метро. Каждая линия - множество станций.
    
    Returns:
        Граф в виде словаря, где ключи - номера линий, а значения - смежные линии.
    """
    graph = defaultdict(set)  # Граф: линия -> множество смежных линий
    
    # Проверяем пересечения между каждой парой линий
    for i in range(len(lines)):
        for j in range(i + 1, len(lines)):
            if lines[i] & lines[j]:  # Если есть общие станции
                graph[i].add(j)
                graph[j].add(i)
    
    return graph


def bfs(graph, start_lines, end_lines):
    """
    Выполняет BFS для поиска минимального числа пересадок.
    
    Args:
        graph: Граф линий метро.
        start_lines: Множество начальных линий (содержащих станцию A).
        end_lines: Множество конечных линий (содержащих станцию B).
    
    Returns:
        Минимальное число пересадок или -1, если путь недостижим.
    """
    queue = deque([(line, 0) for line in start_lines])  # Очередь: линия и число пересадок
    visited = set(start_lines)  # Множество посещенных линий
    
    while queue:
        current_line, transfers = queue.popleft()
        
        # Если достигли одной из конечных линий
        if current_line in end_lines:
            return transfers
        
        # Добавляем в очередь все смежные непосещенные линии
        for neighbor in graph[current_line]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, transfers + 1))
    
    return -1  # Если путь недостижим


def main():
    import sys
    input = sys.stdin.read
    data = input().splitlines()
    
    # Чтение данных
    n = int(data[0])  # Количество станций
    m = int(data[1])  # Количество линий
    
    lines = []  # Список линий метро (каждая линия - множество станций)
    for i in range(2, 2 + m):
        line_data = list(map(int, data[i].split()))
        lines.append(set(line_data[1:]))  # Пропускаем первое число (количество станций)
    
    a, b = map(int, data[2 + m].split())  # Начальная и конечная станции
    
    # Построение графа линий
    graph = build_graph(lines)
    
    # Определение начальных и конечных линий
    start_lines = {i for i, line in enumerate(lines) if a in line}
    end_lines = {i for i, line in enumerate(lines) if b in line}
    
    # Если A или B недостижимы ни на одной линии, возвращаем -1
    if not start_lines or not end_lines:
        print(-1)
        return
    
    # Поиск минимального числа пересадок
    result = bfs(graph, start_lines, end_lines)
    print(result)


if __name__ == '__main__':
    main()

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


Построение графа линий:
Линии метро представляем как множества станций.
Две линии соединены ребром, если у них есть общая станция (станция пересадки).

Определение начальных и конечных линий:
Находим линии, содержащие станции A и B. Начинаем BFS со всех начальных линий и завершаем, если достигаем любую из конечных линий.

BFS для линий:
Очередь содержит пары (линия, число пересадок).
Подсчитываем минимальное число пересадок при достижении конечной линии.
Вывод результата:

Если путь найден, выводим минимальное число пересадок.
Если путь недостижим, выводим −1.

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

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