Алгоритм Форда-Фалкерсона для поиска максимального паросочетания — различия между версиями
(→Идея алгоритма) |
(→Псевдокод) |
||
Строка 23: | Строка 23: | ||
==Псевдокод== | ==Псевдокод== | ||
+ | |||
+ | В массиве <tex>px</tex> хранятся вершины <tex>y \in R</tex>, инцидентные <tex>x_i \in L</tex> в текущем паросочетании, для <tex>py</tex> аналогично. | ||
+ | Максимальное паросочетание - такие ребра <tex>(x, y)</tex>, что <tex>x \in L, y \in R, px[x] == y</tex>. | ||
bool '''dfs'''(x) | bool '''dfs'''(x) | ||
'''if''' vis[x] | '''if''' vis[x] | ||
Строка 32: | Строка 35: | ||
px[x] = y | px[x] = y | ||
return true | return true | ||
− | '''else''' if dfs(py[y]) | + | '''else''' |
− | + | if dfs(py[y]) | |
− | + | py[y] = x | |
− | + | px[x] = y | |
+ | return true | ||
return false | return false | ||
px[] = -1 | px[] = -1 | ||
py[] = -1 | py[] = -1 | ||
− | '''while''' ( | + | is_path = true; |
− | + | '''while''' (is_path) | |
+ | is_path = false | ||
vis[] = false | vis[] = false | ||
'''for''' <tex>x \in L</tex> | '''for''' <tex>x \in L</tex> | ||
'''if''' (px[x] == -1) | '''if''' (px[x] == -1) | ||
− | + | '''if''' dfs(x) | |
− | + | is_path = true | |
[[Категория:Алгоритмы и структуры данных]] | [[Категория:Алгоритмы и структуры данных]] | ||
[[Категория:Задача о паросочетании]] | [[Категория:Задача о паросочетании]] |
Версия 01:06, 24 декабря 2011
Идея алгоритма
Пусть дан неориентированный двудольный граф максимальное паросочетание в нём. Обозначим доли исходного графа как и . Построим граф следующим образом:
и требуется найти(т.е. добавим новый исток и сток );
(проведем ребра из в каждую вершину , из каждой вершины в , и ориентируем все ребра графа так, чтобы они шли от к ).
Изначально максимальное паросочетание пусто.
- Ищем в графе путь из в поиском в глубину.
- Если путь найден, инвертируем все рёбра на пути (ребро становится ребром ). После этого перезаписываем текущее паросочетание так, чтобы в него входили ребра этого пути, ведущие из в .
- Если путь не был найден, значит текущее паросочетание является максимальным, и алгоритм завершает работу. Иначе переходим к пункту 1.
Корректность алгоритма
- Путь из в является дополняющей цепью для исходного графа .
- Инвертация ребер не меняет пути, следовательно, он остается дополняющей цепью.
- В найденном пути вершины не повторяются (это свойство поиска в глубину), тогда множество ребер, ведущих только из в является паросочетанием.
- Путь не был найден. Это значит, что не существует дополняющей цепи для графа теореме текущее паросочетание является максимальным. . Тогда по
Оценка производительности
Поиск в глубину запускается от вершины
не более чем раз, т.к. из ведет ровно ребер, и при каждом запуске одно из них инвертируется. Сам поиск работает за , каждая инвертация и перезапись паросочетания так же занимает времени. Тогда все время алгоритма ограничено .Псевдокод
В массиве
хранятся вершины , инцидентные в текущем паросочетании, для аналогично. Максимальное паросочетание - такие ребра , что . bool dfs(x)
if vis[x]
return false
vis[x] = true
for
if py[y] = -1
py[y] = x
px[x] = y
return true
else
if dfs(py[y])
py[y] = x
px[x] = y
return true
return false
px[] = -1
py[] = -1
is_path = true;
while (is_path)
is_path = false
vis[] = false
for
if (px[x] == -1)
if dfs(x)
is_path = true