К содержанию

Подтема 5 из 6

Другие вопросы о путях

Сколько путей, самый длинный путь, наименьшее и наибольшее число рёбер: что поменять в функции f.

Одна схема

В подборках спрашивают не только кратчайший путь: сколько всего путей, какой путь самый длинный, сколько в пути рёбер. Нужна ли для каждого вопроса своя идея?

Нет, функция та же. Меняются три места: что вернуть в цели, что вернуть в тупике и как собрать ответы соседей. Остальное — словарь из файла, перебор стрелок, @cache — не трогаем.

ВопросВ целиВ тупикеКак собрать
кратчайший путь0∞min(w + f(u))
самый длинный путь0−∞max(w + f(u))
число путей10сумма f(u)
наименьшее число рёбер0∞min(1 + f(u))
наибольшее число рёбер0−∞max(1 + f(u))

Значение в тупике — всегда «худшее, что может быть» для этого вопроса: оно не должно выиграть сравнение. Для минимума это ∞, для максимума −∞, для суммы — 0: путь в тупик в число путей до цели не входит. Разберём каждый вопрос на учебном графе.

Число путей

Сколько путей ведёт из 1 в 100?

Каждый путь из v начинается какой-то стрелкой, поэтому число путей из v — сумма чисел путей из концов её стрелок. В цели путь один — пустой, «уже пришли». Ноль в цели всё бы обнулил: любая сумма нулей — ноль.

from functools import cache graph = {}for line in open("23.txt"):    a, b, w = line.split()    a, b, w = int(a), int(b), float(w)    if a not in graph:        graph[a] = []    graph[a].append((b, w))  @cachedef count(v):    if v == 100:        return 1    total = 0    for u, w in graph.get(v, []):        total += count(u)    return total  print(count(1), count(6))
3 4

Из 7 и из 4 к цели ведёт по одному пути, из 1 — 1 + 1 + 1 = 3: через 7, через 4 и напрямую. Из 6 — путь через 7 и три пути через 1, всего 4.

Под вершинами — число путей до 100. У каждой вершины оно равно сумме чисел у концов её стрелок; у тупика 12 — ноль.

Путей бывают миллиарды, но Python считает целые числа без переполнения, а @cache не даёт перебирать их по одному. Число путей через ребро a → b — произведение: число путей до a, умноженное на число путей от b. Каждый путь до a можно склеить с каждым путём от b.

Самый длинный путь

Какой путь из 1 в 100 самый длинный?

Тот же расчёт с max вместо min. А в тупике теперь −∞ — иначе путь, упёршийся в тупик, мог бы победить.

@cachedef longest(v):    if v == 100:        return 0    best = float("-inf")    for u, w in graph.get(v, []):        best = max(best, w + longest(u))    return best  print(longest(1), longest(6))
12.0 13.0

Из 1 самый длинный путь — прямая стрелка 1 → 100 за 12.0, из 6 — 6 → 1 → 100 за 13.0. Если бы из 1 вела стрелка в тупик весом 20, то с нулём в тупике ответ стал бы 20 — длина пути, который до 100 не доходит. С −∞ такая стрелка никогда не выигрывает максимум.

Бывает и другой вопрос: самый длинный путь из вершины до любого тупика. Тогда цели нет, и ноль возвращают как раз в тупике — там, где путь закончился:

@cachedef to_dead_end(v):    if v not in graph:        return 0    best = float("-inf")    for u, w in graph[v]:        best = max(best, w + to_dead_end(u))    return best  print(to_dead_end(6))
14.0

Из 6 это 6 → 1 → 100 → 12: 1.0 + 12.0 + 1.0 = 14. Тупиков в этом графе один — вершина 12.

Число рёбер

Из какого наименьшего числа рёбер может состоять путь из 1 в 100?

Это тот же кратчайший путь, только каждое ребро весит 1: вместо w прибавляем 1. Веса из файла читаем, как обычно, но не используем.

@cachedef fewest(v):    if v == 100:        return 0    best = float("inf")    for u, w in graph.get(v, []):        best = min(best, 1 + fewest(u))    return best  print(fewest(1), fewest(6))
1 2

Из 1 хватает одного ребра — 1 → 100, из 6 нужно два: 6 → 7 → 100. Наибольшее число рёбер — тот же код с max и −∞ в тупике: из 1 это 2, из 6 — 3.

Итого

  • Что меняетсязначение в цели, в тупике и как собрать ответы
  • Число путейв цели 1, в тупике 0, сумма
  • Через ребро a → bпутей до a × путей от b
  • Самый длинный путьmax, в тупике −∞
  • До любого тупикацели нет, 0 в тупике, max
  • Число рёбервместо веса прибавляем 1

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1
Сколько путей ведёт из 1 в 12 в учебном графе?
ОтветСкрыть ответ
Ответ
Три: в 12 можно попасть только из 100, а из 1 в 100 ведут три пути.
Вопрос 2
Почему в функции подсчёта путей в цели возвращают 1, а не 0?
ОтветСкрыть ответ
Ответ
Дойдя до цели, мы нашли один путь. С нулём в цели все суммы были бы нулями.
Вопрос 3
Сколько путей из 6 в 100 проходит по ребру 6 → 1?
ОтветСкрыть ответ
Ответ
Три: до 6 путь один — пустой, от 1 до 100 — три пути, 1 × 3 = 3.
Вопрос 4
Почему для самого длинного пути в тупике возвращают −∞, а не 0?
ОтветСкрыть ответ
Ответ
С нулём путь, упёршийся в тупик, участвовал бы в максимуме и мог бы победить, хотя до цели он не доходит.
Вопрос 5
Из какого наибольшего числа рёбер состоит путь из 6 в 100?
ОтветСкрыть ответ
Ответ
Из трёх: 6 → 1 → 7 → 100 или 6 → 1 → 4 → 100.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Пути через ребро

В текстовом файле 23-4.txt содержится описание ациклического ориентированного взвешенного графа: в каждой строке — номер начальной вершины ребра, номер конечной вершины и вес ребра; числа разделены пробелами и/или табуляциями. Определите количество различных путей из вершины 1 в вершину 100, проходящих по ребру из вершины 472 в вершину 139.

23-4.txtАциклический ориентированный граф: в строке — начало ребра, конец и весТекстовый файл · 1,1 КБ

Введите число.

Самый длинный путь

В текстовом файле 23-4.txt содержится описание ациклического ориентированного взвешенного графа: в каждой строке — номер начальной вершины ребра, номер конечной вершины и вес ребра; числа разделены пробелами и/или табуляциями. Найдите длину самого длинного пути из вершины 1 в вершину 100. В ответ запишите целую часть найденной длины.

23-4.txtАциклический ориентированный граф: в строке — начало ребра, конец и весТекстовый файл · 1,1 КБ

Введите целую часть найденной длины.

Самый длинный путь до тупика

В текстовом файле 23-6.txt содержится описание ациклического ориентированного взвешенного графа: в каждой строке — номер начальной вершины ребра, номер конечной вершины и вес ребра; числа разделены пробелами и/или табуляциями. Вершины, из которых не выходит ни одного ребра, назовём тупиками. Найдите длину самого длинного пути из вершины 1 до какого-либо тупика. В ответ запишите целую часть найденной длины.

23-6.txtАциклический ориентированный граф: в строке — начало ребра, конец и весТекстовый файл · 3,0 КБ

Введите целую часть найденной длины.

Наименьшее число рёбер

В текстовом файле 23-3.txt содержится описание ациклического ориентированного взвешенного графа: в каждой строке — номер начальной вершины ребра, номер конечной вершины и вес ребра; числа разделены пробелами и/или табуляциями. Найдите наименьшее количество рёбер, которое может содержать путь из вершины 1 в вершину 100.

23-3.txtАциклический ориентированный граф: в строке — начало ребра, конец и весТекстовый файл · 2,4 КБ

Введите число.

Наибольшее число рёбер

В текстовом файле 23-3.txt содержится описание ациклического ориентированного взвешенного графа: в каждой строке — номер начальной вершины ребра, номер конечной вершины и вес ребра; числа разделены пробелами и/или табуляциями. Найдите наибольшее количество рёбер, которое может содержать путь из вершины 1 в вершину 100.

23-3.txtАциклический ориентированный граф: в строке — начало ребра, конец и весТекстовый файл · 2,4 КБ

Введите число.