Скачиваний:
37
Добавлен:
02.05.2014
Размер:
181.25 Кб
Скачать

Алгоритм решения.

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

  Две основные процедуры (операции алгоритма):

· операция расстановки пометок;

· операция изменения потока.

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

1)   не помечена;

2)   помечена, но не просмотрена;

3)   помечена и просмотрена.

  Расставлять пометки начнем с источника S. Он получит пометку  Источник помечен, но не просмотрен. Остальные вершины не помечены. Чтобы источник S был помечен и просмотрен, надо поместить все вершины, смежные с  S.

  Вершина  получит пометку , где .

  Теперь все вершины  смежные с S, помечены, но не просмотрены. А вершина S помечена и просмотрена. Начнём просматривать ту из вершин , которая имеет наименьший индекс. Для этого нужно расставить пометки вершинам, смежным с . Если для вершины  выполняется следующее условие , то она получит метку , где . Если же для вершины  выполняется условие , то  получает метку , где . Далее просматриваем следующую вершину, и так до тех пор, пока не пометим сток t или же пока нельзя будет больше пометить ни одной вершины, сток при этом останется не помеченным. Если сток окажется не помеченным, то процесс нахождения максимального потока в сети можно считать законченным, а если сток помечен, то нужно переходить к

процедуре 2.

  Рассмотрим процедуру изменения потока. Если вершина  имеет пометку , то  заменяем на , если же вершина  имеет пометку , то  заменяем на

  Переходим к следующей вершине и так до тех пор, пока не достигнем источника S. Здесь изменение потока прекращается. Далее переходим к процедуре 1 и так до тех пор, пока величину потока уже нельзя изменить.

Программа должна находить максимальный поток во введенную в неё транспортной сети.

Реализация

Программа написана на языке C++ и откомпилирована в Borland C++Builder 6.

#include <iostream.h>

#include <memory.h>

#include <stdio.h>

#include <conio.h>

char* rus (char* st)//функция подключения вывода символов на кириллице

{

unsigned char* p = st;

while (*p)

{

if (*p >= 192)

if (*p<=239)

*p -= 64;

else

*p -= 16;

p++;

}

return st;

}

const int MAX_VERTICES = 40;

int NUM_VERTICES; // число вершин в графе

const int INFINITY = 10000; // условное число обозначающее бесконечность

// f - массив, содержащий текущее значение потока

// f[i][j] - поток, текущий от вершины i к j

int f[MAX_VERTICES][MAX_VERTICES];

// с - массив содержащий вместимости ребер,

// т.е. c[i][j] - максимальная величину потока способная течь по ребру (i,j)

int c[MAX_VERTICES][MAX_VERTICES];

// набор вспомогательных переменных используемых функцией FindPath - обхода в ширину

// Flow - значение потока через данную вершину на данном шаге поиска

int Flow[MAX_VERTICES];

// Link используется для нахождения собственно пути

// Link[i] хранит номер предыдущей вершины на пути i -> исток

int Link[MAX_VERTICES];

int Queue[MAX_VERTICES]; // очередь

int QP, QC; // QP - указатель начала очереди и QC - число эл-тов в очереди

// поиск пути, по которому возможно пустить поток алгоритмом обхода графа в ширину

// функция ищет путь из истока в сток, по которому еще можно пустить поток,

// считая вместимость ребра (i,j) равной c[i][j] - f[i][j],

// т.е. после каждой итерации (одна итерация - один поиск пути) уменьшаем вместимости ребер,

// на величину пущеного потока

int FindPath(int source, int target) // source - исток, target - сток

{

QP = 0; QC = 1; Queue[0] = source;

Link[target] = -1; // особая метка для стока

int i;

int CurVertex;

memset(Flow, 0, sizeof(int)*NUM_VERTICES); // в начале из всех вершин кроме истока течет 0

Flow[source] = INFINITY; // а из истока может вытечь сколько угодно

while (Link[target] == -1 && QP < QC)

{

// смотрим, какие вершины могут быть достигнуты из начала очереди

CurVertex = Queue[QP];

for (i=0; i<NUM_VERTICES; i++)

// проверяем, можем ли мы пустить поток по ребру (CurVertex,i):

if ((c[CurVertex][i] - f[CurVertex][i])>0 && Flow[i] == 0)

{

// если можем, то добавляем i в конец очереди

Queue[QC] = i; QC++;

Link[i] = CurVertex; // указываем, что в i добрались из CurVertex

// и находим значение потока текущее через вершину i

if (c[CurVertex][i]-f[CurVertex][i] < Flow[CurVertex])

Flow[i] = c[CurVertex][i];

else

Flow[i] = Flow[CurVertex];

}

QP++;// прерходим к следующей в очереди вершине

}

// закончив поиск пути

if (Link[target] == -1) return 0; // мы или не находим путь и выходим

// или находим:

// тогда Flow[target] будет равен потоку, который "дотек" по данному пути из истока в сток

// тогда изменяем значения массива f для данного пути на величину Flow[target]

CurVertex = target;

while (CurVertex != source) // путь из стока в исток мы восстанавливаем с помощью массива Link

{

f[Link[CurVertex]][CurVertex] +=Flow[target];

CurVertex = Link[CurVertex];

}

return Flow[target]; // Возвращаем значение потока которое мы еще смогли "пустить" по графу

}

// основная функция поиска максимального потока

int MaxFlow(int source, int target) // source - исток, target - сток

{

// инициализируем переменные:

memset(f, 0, sizeof(int)*MAX_VERTICES*MAX_VERTICES); // по графу ничего не течет

int MaxFlow = 0; // начальное значение потока

int AddFlow;

do

{

// каждую итерацию ищем какй-либо простой путь из истока в сток

// и какой еще поток мажет быть пущен по этому пути

AddFlow = FindPath(source, target);

MaxFlow += AddFlow;

} while (AddFlow >0);// повторяем цикл пока поток увеличивается

return MaxFlow;

}

int main()

{

printf(rus("\n НАХОЖДЕНИЕ МАКСИМАЛЬНОГО ПОТОКА \n"));

printf(rus("\n АЛГОРИТМ ФОРДА-ФАЛКЕРСОНА \n\n"));

printf(rus("\n КУРСОВАЯ РАБОТА ПО ДИСКРЕТНОЙ МАТЕМАТИКЕ \n"));

printf(rus("\n выполнили: Шаяхметов А.Р. , Корпухин М.В. \n\n"));

printf(rus("\n ПО-122 ФИРТ УГАТУ 2007г\n\n"));

printf(rus("\n\n нажмите любую клавишу для продолжения...."));

getch();

clrscr();

int source, target;

printf(rus("\n Введите число вершин в графе\n-->"));

scanf("%d", &NUM_VERTICES);

printf(rus("\n Введите значения истока и стока \n-->"));

scanf("%d %d", &source, &target);

printf(rus("\n Введите матрицу содержащею вместимость ребер: \n "));

printf(rus("каждый элемент - вместимость ребра ведушего \n из вершины с номером его строки к вершине с номером его столбца\n"));

int i, j;

for (i=0; i<NUM_VERTICES; i++)

for (j=0; j<NUM_VERTICES; j++)

scanf("%d",&c[i][j]);

printf(rus("\n максимальный поток равен:"));

printf("%d", MaxFlow(source, target));

getch();

return 0;

}

Соседние файлы в папке Курсовая работа - Задача о максимальном потоке