Опубликован: 05.01.2015 | Уровень: для всех | Доступ: платный
Лекция 21:

Кратчайшие пути

Лемма 21.21. С помощью алгоритма Беллмана-Форда можно решить задачу поиска кратчайшего пути из одного истока в сетях без отрицательных циклов за время, пропорциональное VE.

Доказательство. Мы делаем V проходов по всем E ребрам, поэтому полное время будет пропорционально VE. Чтобы доказать, что это вычисление приведет к нужному результату, покажем методом индукции по i, что для всех вершин v после

i-го прохода значение wt[v] не больше, чем длина кратчайшего пути из s в v, который содержит i или менее ребер. Очевидно, это утверждение верно для i, равного 0. Полагая, что оно истинно для i, рассмотрим два возможных случая для каждой данной вершины v: среди путей из s в v с i + 1 или меньшим количеством ребер либо может, либо не может существовать кратчайший путь с i + 1 ребрами. Если самый короткий из путей с i+1 или менее ребрами из s в v имеет длину i или меньше, то wt[v] не изменится и останется допустимым. Иначе существует путь из s в v с i+1 ребрами, более короткий, чем любой путь из s в v с i или менее ребрами. Этот путь должен состоять из пути с i ребрами из s в некоторую вершину w с добавленным ребром w-v. По предположению индукции, wt[w] содержит верхнюю границу наиболее короткого расстояния из s в w, а (i+1)-й проход проверяет каждое ребро, является ли оно последним ребром в новом кратчайшем пути к конечной вершине ребра. В частности, проверяется ребро w-v.

После V- 1 итераций wt[w] содержит нижнюю границу длины любого кратчайшего пути из s в v с V- 1 или менее ребрами, для всех вершин v. Мы можем остановиться после V- 1 итераций, т.к. любой путь с V или более ребрами должен содержать цикл (с положительной или нулевой стоимостью), и, удалив этот цикл, можно отыскать путь с V- 1 или менее ребрами, который имеет такую же или меньшую длину. Поскольку wt[w] есть длина некоторого пути из s в v, это значение является также верхней границей длины кратчайшего пути, и таким образом, должно быть равно длине кратчайшего пути.

Хотя это и не было указано явно, то же самое доказательство показывает, что вектор spt содержит указатели на ребра в дереве кратчайших путей с корнем в s. $\blacksquare$

Для типичных графов проверка каждого ребра на каждом проходе достаточно расточительна. Действительно, можно сразу легко определить, что многие ребра не приводят к успешной релаксации на любом проходе. Фактически, что-то изменить могут только ребра, исходящие из вершины, значение которой изменилось на предыдущем проходе.

Программа 21.9 является прямой реализацией описанного алгоритма с использованием очереди FIFO, содержащей эти ребра, которые будут проверяться на каждом проходе. На рис. 21.30 приведен пример работы этого алгоритма.

Программа 21.9. Алгоритм Беллмана-Форда

Эта реализация алгоритма Беллмана-Форда использует очередь FIFO всех вершин, для которых может оказаться эффективной релаксация по исходящему ребру. Мы выбираем вершину из очереди и выполняем релаксацию по всем ее ребрам. Если любое из них приводит к более короткому пути в некоторую вершину, мы заносим ее в очередь. Сигнальное значение G->V отделяет текущую серию вершин (которые изменились на последней итерации) от следующей серии (которые изменяются на данной итерации) и позволяет остановиться после G->V проходов.

  SPT(Graph &G, int s) : G(G),
    spt(G.V()), wt(G.V(), G.V())
    { QUEUE<int> Q; int N = 0;
      wt[s] = 0.0;
      Q.put(s); Q.put(G.V());
      while (!Q.empty())
        { int v;
          while ((v = Q.get()) == G.V())
            { if (N++ > G.V()) return; Q.put(G.V()); }
          typename Graph::adjIterator A(G, v);
          for (Edge* e = A.beg(); !A.end(); e = A.nxt())
            { int w = e->w();
              double P = wt[v] + e->wt();
              if ( P < wt[w])
                { wt[w] = P; Q.put(w); spt[w] = e; }
            }
        }
    }
      
 Алгоритм Беллмана-Форда (с отрицательными весами)

Рис. 21.30. Алгоритм Беллмана-Форда (с отрицательными весами)

На этом рисунке показан результат поиска алгоритмом Беллмана-Форда кратчайших путей из вершины 4 в сети с рис. 21.26. Алгоритм выполняет проходы, в которых проверяет все ребра, исходящие из всех вершин в очереди FIFO. Содержимое очереди показано под каждым чертежом графа, где затененные элементы представляют содержимое очереди, оставшееся с предыдущего прохода.

Когда мы находим ребро, которое может уменьшить длину пути из вершины 4 в конечную вершину этого ребра, мы выполняем операцию релаксации, которая помещает конечную вершину в очередь, а ребро - в SPT. Серые ребра на чертежах графа образуют SPT после каждого этапа, которое показано также в ориентированной форме в центре (все ребра ориентированы вниз). Мы начинаем с пустого SPT и вершины 4 в очереди (вверху). На втором проходе мы выполняем релаксацию вдоль ребер 4-2 и 4-3 и оставляем в очереди вершины 2 и 3.

На третьем проходе мы проверяем, но не выполняем релаксацию вдоль 2-3, а затем выполняем релаксацию вдоль 3-0 и 3-5, оставив в очереди вершины 0 и 5. На четвертом проходе мы выполняем релаксацию вдоль 5-1 и затем проверяем, но не выполняем релаксацию вдоль 1-0 и 1-5, оставив в очереди вершину 1. На последнем проходе (внизу) мы выполняем релаксацию вдоль 1-2. Алгоритм вначале действует как BFS, однако в отличие от всех других методов поиска на графах, он может изменять ребра дерева, как на последнем шаге.

Программа 21.9 эффективно решает задачи поиска кратчайших путей в реальных сетях с одним истоком, однако быстродействие в худшем случае все-таки остается пропорциональным VE. Для плотных графов время выполнения не лучше, чем для алгоритма Флойда, который находит все кратчайшие пути, а не только исходящие из одного истока. Для разреженных графов реализация алгоритма Беллмана-Форда в программе 21.9 может работать быстрее алгоритма Флойда вплоть до в V раз. Однако она работает почти в V раз медленнее, чем алгоритм Дейкстры в худшем случае на сетях без ребер с отрицательными весами (см. таблицу 19.2).

Были исследованы и другие вариации алгоритма Беллмана-Форда, и некоторые из них быстрее работают для задачи с одним истоком, чем версия с очередью FIFO в программе 21.9, но все они в худшем случае требуют времени, пропорционального по крайней мере VE (см., например, упражнение 21.132). Базовый алгоритм Беллмана-Форда был разработан десятки лет тому назад и, несмотря на впечатляющие достижения в повышении эффективности для множества других задач на графах, до сих пор не были открыты алгоритмы с лучшей эффективностью в худшем случае на сетях с отрицательными весами.

Кроме того, алгоритм Беллмана-Форда более эффективен, чем алгоритм Флойда, для обнаружения в сетях отрицательных циклов.

Лемма 21.22. С помощью алгоритма Беллмана-Форда можно решить задачу обнаружения отрицательного цикла за время, пропорциональное VE.

Доказательство. Основные положения доказательства леммы 21.21 справедливы даже при наличии отрицательных циклов. Если мы выполняем V-ю итерацию алгоритма, и один из шагов релаксации завершается успешно, то мы обнаружили кратчайший путь с V ребрами, который соединяет вершину s с некоторой вершиной в сети. Любой такой путь должен содержать цикл (соединяющий некоторую вершину w с собой), и в соответствии с предположением индукции этот цикл должен быть отрицательным: ведь чтобы w была включена в путь второй раз, путь из s во второе вхождение w должен быть короче пути из s в первое вхождение w. Этот цикл будет также присутствовать в дереве, поэтому обнаружить циклы можно и с помощью периодической проверки ребер из spt (см. упражнение 21.134).

Сказанное верно только для тех вершин, которые находятся в том же сильно связном компоненте, что и исток s. Чтобы обнаружить отрицательные циклы вообще, можно также вычислить сильно связные компоненты и обнулить веса для одной вершины в каждом компоненте (см. упражнение 21.126) или добавить фиктивную вершину с ребрами в каждую из остальных вершин (см. упражнение 21.127). $\blacksquare$

В заключение этого раздела рассмотрим задачу поиска кратчайших путей для всех пар вершин. Можно ли улучшить алгоритм Флойда, который выполняется за время, пропорциональное V3 ? Использование алгоритма Беллмана-Форда для решения задачи для всех пар вершин с помощью решения для каждой вершины задачи с одним истоком даст время выполнения в худшем случае, пропорциональное V2E . Мы не рассматриваем это решение более подробно, поскольку существует способ, гарантирующий решение задачи поиска всех путей за время, пропорциональное VE log К Он основан на идее, рассмотренной в начале этого раздела: преобразование исходной сети в сеть, которая содержит только неотрицательные веса и имеет такую же структуру кратчайших путей.

Фактически, у нас имеется большая свобода при преобразовании одной сети в другую с другими весами ребер, но с теми же кратчайшими путями. Предположим, что индексированный именами вершин вектор wt содержит произвольное присваивание весов вершинам сети G. Для этих весов определим операцию перевзвешивания (reweighting) графа следующим образом:

  • Чтобы перевзвесить ребро, необходимо добавить к весу этого ребра разность между весами начальной и конечной вершин ребра.
  • Чтобы перевзвесить сеть, необходимо перевзвесить все ребра сети.

Например, следующий простой код перевзвешивает сеть в соответствии с принятыми соглашениями:

  for (v = 0; v < G->V(); v++)
    { typename Graph::adjIterator A(G, v);
      for (Edge* e = A.beg(); !A.end(); e = A.nxt())
        e->wt() = e->wt() + wt[v] - wt[e->w()]
        }
      

Эта операция - простой линейный по времени процесс, который определен для всех сетей, независимо от весов. При этом кратчайшие пути в полученной сети остаются теми же, что и кратчайшие пути в исходной сети.

Лемма 21.23. Перевзвешивание сети не изменяет ее кратчайшие пути.

Доказательство. Для любых двух заданных вершин s и t перевзвешивание изменяет вес любого пути из s в t в точности на разность весов s и t. Это утверждение легко доказать методом индукции по длине пути. При перевзвешивании сети вес каждого пути из s в t изменяется на одно и то же значение, каким бы путь ни был - длинным или коротким. В частности, из этого факта непосредственно следует, что длина кратчайшего пути между любыми двумя вершинами в преобразованной сети совпадает с длиной кратчайшего пути между ними в исходной сети. $\blacksquare$

Поскольку пути между различными парами вершин могут быть перевзвешены по-разному, перевзвешивание может повлиять на такие задачи, в которых выполняется сравнение длин кратчайших путей (например, вычисление диаметра сети). В таких случаях после вычисления кратчайших путей, но перед использованием результатов, следует обратить перевзвешивание.

Перевзвешивание бесполезно в случае сетей с отрицательными циклами: эта операция не изменяет вес ни одного цикла, поэтому она не может удалить отрицательные циклы. Но для сетей без отрицательных циклов можно попытаться найти такое множество весов вершин, что перевзвешивание приведет к неотрицательным весам ребер, независимо от того, какими были первоначальные веса. С неотрицательными весами ребер мы можем затем решить задачу поиска кратчайших путей для всех пар вершин с помощью версии алгоритма Дейкстры для всех пар вершин. Например, на рис. 21.31 приведен такой пример для нашей демонстрационной сети, а на рис. 21.32 - вычисление кратчайших путей алгоритмом Дейкстры в преобразованной сети без отрицательных ребер. Следующая лемма показывает, что такое множество весов можно найти всегда.

Лемма 21.24. В произвольной сети без отрицательных циклов выберем любую вершину s и присвоим каждой вершине v вес, равный длине кратчайшего пути в v из s. Перевзвешивание сети с весами этих вершин дает в результате неотрицательные веса ребер для каждого ребра, которое соединяет вершины, достижимые из s.

Доказательство. Для любого заданного ребра v-w вес v равен длине кратчайшего пути в v, а вес w равен длине кратчайшего пути в w. Если v-w - конечное ребро на кратчайшем пути в w, то разность между весом w и весом v в точности равна весу v-w. Другими словами, перевзвешивание ребра даст нулевой вес. Если кратчайший путь через w не проходит через v, то вес v плюс вес v-w должен быть больше или равен весу w. То есть перевзвешивание ребра даст положительный вес. $\blacksquare$

 Перевзвешивание сети

Рис. 21.31. Перевзвешивание сети

Для любого распределения весов на вершинах (вверху) можно выполнить перевзвешивание всех ребер в сети, добавив к весу каждого ребра разность весов его начальной и конечной вершин. Перевзвешивание не влияет на кратчайшие пути, поскольку оно одинаково изменяет веса всех путей, соединяющих каждую пару вершин. Вот, например, путь 0-5-4-2-3: его вес в первоначальной сети равен 0.29 + 0.21 + 0.32 + 0.50 = 1.32, а в перевзвешенной сети - 1.12 + 0.19 + 0.12 + 0.34 = 1.77; эти веса отличаются на 0.45 = 0.81 - 0.36, т.е. на разность весов вершин 0 и 3. Веса всех путей между 0 и 3 изменились на одну и ту же величину.

Как в случае применения алгоритма Беллмана-Форда для обнаружения отрицательных циклов, существуют два способа сделать вес каждого ребра неотрицательным в произвольной сети без отрицательных циклов. Либо можно начать с истока в каждом сильно связном компоненте, либо добавить фиктивную вершину с ребром нулевой длины в каждую вершину сети. В любом случае получится остовный лес кратчайших путей, которым можно воспользоваться для присвоения весов вершинам (вес пути из корня в данную вершину в ее SPT).

Например, значения весов, выбранные на рис. 21.31, в точности равны длинам кратчайших путей из вершины 4, поэтому ребра в дереве кратчайших путей с корнем в 4 имеют нулевые веса в перевзвешенной сети.

Итак, мы можем решить задачу поиска кратчайших путей для всех пар вершин в сетях, которые содержат отрицательные веса ребер, но не имеют отрицательных циклов, следующим образом:

  • При помощи алгоритма Беллмана-Форда находим лес кратчайших путей в исходной сети.
  • Если алгоритм обнаружил отрицательный цикл, сообщаем об этом и завершаем работу.
  • Перевзвешиваем сеть на основе леса.
  • Применяем версию алгоритма Дейкстры для всех пар вершин к перевзвешенной сети.

После этих вычислений матрица путей содержит кратчайшие пути в обеих сетях, а матрица расстояний - длины путей в перевзвешенной сети. Эта последовательность шагов иногда называется алгоритмом Джонсона (Johnson) (см. раздел ссылок).

Лемма 21.25. С помощью алгоритма Джонсона можно решить задачу поиска кратчайших путей для всех пар вершин в сетях без отрицательных циклов за время, пропорциональное $VE\log_{d}{V}$, где d = 2, если E < 2V, и d = E/V в противном случае.

Доказательство. См. леммы 21.22-21.24 и резюме, подведенное в предыдущем абзаце. Граница времени выполнения в худшем случае непосредственно вытекает из лемм 21.7 и 21.22. $\blacksquare$

 Все кратчайшие пути в перевзвешенной сети

Рис. 21.32. Все кратчайшие пути в перевзвешенной сети

Здесь приведены SPT-деревья для каждой вершины в обращении перевзвешенной сети с рис. 21.31, которые можно получить с помощью алгоритма Дейкстры, вычислив кратчайшие пути в исходной сети с рис. 21.26 рис. 21.26. Эти пути совпадают с путями сети до перевзвешивания.

Как на рис. 21.9, векторы st на этих диаграммах представляют собой столбцы матрицы путей из рис. 21.26. Векторы wt в этой схеме являются столбцами матрицы расстояний, но необходимо отменить пере-взвешивание для каждого элемента, вычтя вес начальной вершины и прибавив вес конечной вершины пути (см. рис. 21.31). Например, из третьей строки снизу можно видеть, что в обеих сетях кратчайшим путем из 0 в 3 будет 0-5-1-4-3, а его длина равна 1.13 в приведенной здесь перевзвешенной сети. Сравнивая с рис. 21.31, можно вычислить его длину в исходной сети: вычтя вес 0 и прибавив вес 3, получим результат 1.13 - 0.81 + 0.36 = 0.68, т.е. элемент в строке 0 и столбце 3 матрицы расстояний с рис. 21.26. Все кратчайшие пути, ведущие в вершину 4 в этой сети, имеют нулевцю длину, поскольку они использовались для перевзвешивания.

Для реализации алгоритма Джонсона мы объединяем реализацию из программы 21.9, код перевзвешивания, приведенный перед леммой 21.23, и реализацию алгоритма Дейкстры поиска кратчайших путей для всех пар вершин из программы 21.4 (или из программы 20.6 в случае плотных графов). Как было сказано в доказательстве леммы 21.22, для сетей, которые не являются сильно связными, придется соответствующим образом подправить алгоритм Беллмана-Форда (см. упражнения 21.135-21.137). Чтобы завершить реализацию интерфейса поиска кратчайших путей для всех пар вершин, можно либо вычислить истинные длины путей, вычитая вес начальной и прибавляя вес конечной вершины (т.е. отменить операцию перевзвешивания для путей) при копировании двух векторов в матрицы расстояний и путей в алгоритме Дейкстры, либо поместить эти вычисления в функцию GRAPHdist в реализации АТД.

Для сетей без отрицательных весов задача выявления циклов решается более просто, чем задача вычисления кратчайших путей из одного истока до всех других вершин; а последняя задача решается проще, чем задача вычисления кратчайших путей, соединяющих все пары вершин. Все это соответствует нашим интуитивным представлениям. Но вот аналогичные факты для сетей, которые содержат отрицательные веса, кажутся противоестественными: алгоритмы, изученные в этом разделе, показывают, что для сетей с отрицательными весами лучшие из известных алгоритмов решения трех рассмотренных задач имеют похожие характеристики производительности в худшем случае. Например, в худшем случае определить, содержит ли сеть единственный отрицательный цикл, примерно столь же сложно, как и найти все кратчайшие пути в сети того же размера без отрицательных циклов.

Упражнения

21.109. Измените генераторы случайных сетей из упражнений 21.6 и 21.7, чтобы с помощью масштабирования выдавать веса из диапазона от а до b (где а и b принимают значения между -1 и 1).

21.110. Измените генераторы случайных сетей из упражнений 21.6 и 21.7, чтобы порождать отрицательные веса, изменяя знаки фиксированного процента (значение которого задается клиентом) весов ребер.

21.111. Разработайте клиентские программы, которые используют генераторы из упражнений 21.109 и 21.110 для генерации сетей, содержащих большой процент отрицательных весов, но не более чем несколько отрицательных циклов, для как можно большего интервала значений V и E.

21.112. Найдите (в интернете или газетах) таблицу конвертации валют. Воспользуйтесь ей для построения таблицы арбитражных операций. Примечание: не берите таблицы, которые выводятся/рассчитываются из небольшого количества значений и которые поэтому не дают достаточно точной информации о курсах. Дополнительный совет: порвите всех на валютной бирже!

21.113. Постройте последовательность арбитражных таблиц, используя источник, найденный в упражнении 21.112 (каждый источник периодически публикует различные таблицы). Найдите в таблицах все возможности для совершения арбитражных операций и попытайтесь определить их характерные особенности. Например, сохраняются ли удобные возможности на протяжении нескольких дней, или же они быстро восстанавливаются сразу после возникновения?

21.114. Разработайте модель для генерации случайных задач арбитражных операций. Цель - генерировать таблицы, которые как можно более похожи на таблицы, используемые в упражнении 21.113.

21.115. Разработайте модель для генерации случайных задач календарного планирования с конечными сроками. Цель - генерировать нетривиальные, но обычно выполнимые задачи.

21.116. Измените интерфейс и реализации из упражнения 21.101, чтобы дать клиентам возможность ставить и решать задачи календарного планирования с конечными сроками, используя сведение к задаче поиска кратчайших путей.

21.117. Найдите ошибку в следующем рассуждении. Задача поиска кратчайших путей сводится к задаче разностных ограничений с помощью построения, используемого в доказательстве леммы 21.15, а задача разностных ограничений тривиально сводится к линейному программированию - поэтому, согласно лемме 21.17, линейное программирование является NP-трудным.

21.118. Сводится ли задача поиска кратчайших путей в сетях без отрицательных циклов к задаче календарного планирования с конечными сроками? (Эквивалентны ли эти две задачи?) Обоснуйте свой ответ.

21.119. Найдите цикл с наименьшим весом (лучшую возможность для совершения арбитражной операции) в примере, показанном на рис. 21.27.

21.120. Докажите, что задача поиска цикла наименьшего веса в сети, которая может содержать ребра с отрицательными весами, является NP-трудной.

21.121. Покажите, что алгоритм Дейкстры работает правильно для сети, в которой ребра, исходящие из истока, являются единственными ребрами с отрицательными весами.

21.122. Разработайте класс, основанный на алгоритме Флойда, который предоставляет клиентам возможность проверить наличие в сети отрицательных циклов.

21.123. Воспользовавшись алгоритмом Флойда, покажите в стиле рис. 21.29 вычисление всех кратчайших путей для сети, определенной в упражнении 21.1, но с отрицательными весами ребер 5-1 и 4-2.

21.124. Является ли алгоритм Флойда оптимальным для полных сетей (с V2 ребрами)? Обоснуйте свой ответ.

21.125. Покажите в стиле рис. 21.32 вычисление с помощью алгоритма Белл-мана-Форда всех кратчайших путей сети, определенной в упражнении 21.1, но с отрицательными весами ребер 5-1 и 4-2.

21.126. Разработайте класс, основанный на алгоритме Беллмана-Форда, который позволяет клиентам проверить наличие в сети отрицательных циклов, используя метод отдельного истока в каждом сильно связном компоненте.

21.127. Разработайте класс, основанный на алгоритме Беллмана-Форда, который позволяет клиентам проверить наличие в сети отрицательных циклов, используя фиктивную вершину с ребрами во все вершины сети.

о 21.128. Приведите семейство графов, для которых программа 21.9 затрачивает на поиск отрицательных циклов время, пропорциональное VE.

21.129. Покажите расписание, которое вычисляется программой 21.9 для задачи календарного планирования с конечными сроками из упражнения 21.89.

21.130. Докажите, что следующий обобщенный алгоритм решает задачу поиска кратчайших путей с одним истоком: " Выполнить релаксацию произвольного ребра; продолжать так, пока существуют ребра, для которых можно выполнить релаксацию " .

21.131. Измените реализацию алгоритма Беллмана-Форда в программе 21.9, используя в ней рандомизированную очередь вместо очереди FIFO. (Корректность этого метода доказана в упражнении 21.130.)

21.132. Измените реализацию алгоритма Беллмана-Форда в программе 21.9, чтобы вместо очереди FIFO использовать дек, в который ребра помещаются в соответствии со следующим правилом: если ребро уже находилось в деке, поместить его в начало (как в стеке), а если оно встречается в первый раз, то поместить его в конец (как в очереди).

21.133. Эмпирически сравните производительность реализаций из упражнений 21.131 и 21.132 с программой 21.9 на различных общих сетях (см. упражнения 21.109-21.111).

21.134. Измените реализацию алгоритма Беллмана-Форда в программе 21.9, чтобы реализовать функцию, которая возвращает индекс произвольной вершины из любого отрицательного цикла или -1, если сеть не содержит отрицательных циклов. При наличии отрицательного цикла эта функция должна также построить такой вектор spt, что переходы по ссылкам в этом векторе (начиная с возвращаемого значения) выполняют обход цикла.

21.135. Измените реализацию алгоритма Беллмана-Форда в программе 21.9, чтобы установить веса вершин так, как нужно для алгоритма Джонсона, воспользовавшись следующим методом. Каждый раз, когда очередь становится пустой, в векторе spt ищется вершина, вес которой еще не установлен, и алгоритм запускается повторно с этой вершиной в качестве истока (для установки весов всех вершин, находящихся в том же сильно связном компоненте, что и новый исток). Такая процедура повторяется, пока не будут обработаны все сильно связные компоненты.

21.136. Разработайте реализацию интерфейса АТД поиска кратчайших путей для всех пар вершин в разреженных сетях (основанную на алгоритме Джонсона), внеся соответствующие изменения в программы 21.9 и 21.4.

21.137. Разработайте реализацию интерфейса АТД поиска кратчайших путей для всех пар вершин в насыщенных сетях (основанную на алгоритме Джонсона) (см. упражнения 21.136 и 21.43). Эмпирически сравните полученную реализацию с алгоритмом Флойда (программа 21.5) для различных сетей общего вида (см. упражнения 21.109-21.111).

21.138. Добавьте в решение упражнения 21.137 функцию-член, которая позволяет клиенту уменьшить стоимость ребра. Она должна возвращать флаг, который указывает, создает ли это действие отрицательный цикл. Если нет, то необходимо обновить матрицы путей и расстояний, чтобы они содержали новые кратчайшие пути. Функция должна выполняться за время, пропорциональное V 2.

21.139. Добавьте в решение упражнения 21.138 функции-члены, которые позволяют клиентам вставлять и удалять ребра.

21.140. Разработайте алгоритм, который преодолевает барьер VE для задачи поиска кратчайших путей в общих сетях с одним истоком для частного случая, когда известно, что абсолютные значения весов ограничены некоторой константой.

Бактыгуль Асаинова
Бактыгуль Асаинова

Здравствуйте прошла курсы на тему Алгоритмы С++. Но не пришел сертификат и не доступен.Где и как можно его скаачат?

Александра Боброва
Александра Боброва

Я прошла все лекции на 100%.

Но в https://www.intuit.ru/intuituser/study/diplomas ничего нет.

Что делать? Как получить сертификат?

Александр Ефимов
Александр Ефимов
Россия, Спб, СпбГтурп
Павел Сусликов
Павел Сусликов
Россия