![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Глава 22. Потоки в сетях. Такой подход позволяет отделить абстракцию, необходимую рассматриваемым нами алгоритмам (ребра идут в обоих направлениях)
Поскольку транспортные сети, как правило, разрежены, мы воспользуемся классом GRAPH, в основу которого положено представление графа в виде списка смежных вершин, подобное реализации класса SparceMultiGRAPH (разреженный мультиграф) из программы 20.5. Что более важно, типовые транспортные сети могут иметь параллельные ребра (различной пропускной способности), соединяющие две вершины. Такая ситуация не требует специальных мер с применением класса SparceMultiGRAPH, тем не менее, в случае представления графа в виде матрицы смежности, клиенты должны объединить все параллельные ребра в одно ребро. В сетях, представленных в главах 20 и 21, мы пришли к соглашению о том, что веса представляются вещественными числами в диапазоне от 0 до 1. В этой главе мы полагаем, что веса (пропускная способность и величина потоков) суть m-разрядные целые числа (в промежутке от 0 до 2т-1). Это мы делаем, по меньшей мере, по двум причинам. Во-первых, нам довольно часто придется проверять на равенство различные комбинации весов, и делать это в представлении соответствующих величин в виде вещественных чисел с плавающей точкой может оказаться неудобным. Во-вторых, время выполнения рассматриваемых нами алгоритмов может зависеть от относительных значений весов, а параметр M = 2™ дает удобный способ ограничения значений весов. Например, отношение наибольшего веса к наименьшему ненулевому весу принимает значение, меньшее М. Использование целочисленных весов есть одна из многочисленных возможных альтернатив (см., например, упражнение 20.8), которые мы можем выбрать при решении такого рода задач. Иногда нам приходится рассматривать ребра с неограниченной пропускной способностью. Это может означать, что мы не соотносим поток с пропускной способностью такого ребра, либо мы можем воспользоваться сигнальным значением, которое принимает заведомо большее значение, чем величина любого потока. Программа 22.1 представляет собой клиентскую функцию, которая проверяет, удовлетворяют ли потоки условию равновесия в каждом узле и возвращает значение величины потока, если поток удовлетворяет этому условию. В большинстве случаев мы включаем вызов этой функции в алгоритм вычисления максимального потока в качестве заключительной операции. Несмотря на все доверие, которое мы испытываем к свойству 22.1, характерная для всех программистов параноидная подозрительность нашептывает нам, что мы должны также проверить, равен ли поток, истекающий из истока, потоку, втекающему в сток. Возможно, мы благоразумно поступим, если проверим, что ни в одном ребре поток не превосходит по величине пропускную способность этого ребра и что структуры данных внутренне непротиворечивы (см. упражнение 22.12). Часть 5. Алгоритмы на графах
За счет обращения к функции flow(G, v) вычисляется разность между втекающим и вытекающим потоками в вершине v сети G. Посредством вызова flow(G, s, t) проверяются величины потоков сети из истока (s) в сток (t), при этом 0 возвращается в тех случаях, когда втекающий поток в некотором внутреннем узле не равен вытекающему потоку или если величина какого-либо потока принимает отрицательное значение; в противном случае возвращается величина потока. template < class Graph, class Edge> class check public: static int flow (Graph & G, int v) { int x = 0; typename Graph:: adjIterator A(G, v); for (Edge* e = A.beg();! A.end(); e = A.nxt()) x += e-> from(v)? e-> flow(): -e-> flow(); return x; static bool flow (Graph & G, int s, int t) for (int v = 0; v < G.V(); v++) if ((v! = s) & & (v! = t)) if (flow(G, v)! = 0) return false; int sflow = flow(G, s); if (sflow < 0) return false; if (sflow + flow(G, t)! = 0) return false; return true;
|