Алгоритм вырезания соцветий
Содержание
Паросочетание в недвудольном графе
Определение: |
Соцветие | графа - цикл, состоящий из ребер, из которых только входят в соцветие .
Определение: |
Cжатие соцветия - граф | , полученный из сжатием соцветия в одну псевдо-вершину.
Определение: |
База соцветия - вершина соцветия, в которую входит ребро не из данного соцветия. |
Теорема Эдмондса
Теорема: |
Пусть в графе существует соцветие .Тогда в существует удлиняющий путь тогда и только тогда, когда существует удлиняющий путь в |
Доказательство: |
Пусть граф
Пусть путь
Пусть путь Рассмотрим отдельно случай, когда Пусть теперь путь начинается со сжатого соцветия , т.е. имеет вид . Тогда в соцветии найдётся соответствующая вершина , которая связана ребром с . Заметим, что из базы соцветия всегда найдётся чередующийся путь чётной длины до вершины . Учитывая всё вышесказанное, получаем, что путь является увеличивающим путём в графе . проходит через псевдо-вершину , но не начинается и не заканчивается в ней. Тогда в есть два ребра, проходящих через , пусть это и . Одно из них обязательно должно принадлежать паросочетанию, однако, так как база цветка не насыщена, а все остальные вершины цикла цветка насыщены рёбрами цикла, то мы приходим к противоречию (это эквивалентно случаю отсутствия ребра из ). Таким образом, этот случай просто невозможен. Теорема доказана. в |
Алгоритм вырезания соцветий
Пусть дан произвольный граф
Общая идея
- Сжимаем все соцветия
- Находим паросочетания в полученном графе поиском в глубину/ширину.
- Разжимаем соцветия, восстанавливая паросочетание.
Пошаговое представление
Алгоритм строит лес, содержащий деревья удлиняющих путей, корнями которых являются вершины не из паросочетания.
Разобьем каждое неориентированное ребро
на два ориентированных ребра и . Каждое ребро может принимать одно из трех состояний: непосещенное, четное и нечетное. Для каждой вершины из паросочетания в будем хранить вершину, смежную . Также для каждой вершины алгоритм в будет хранить родителя в дереве обхода.Сначала пометим все вершины, включенные в паросочетание, непосещенными, все остальные - четными.
Пока существует удлиняющий путь или пока есть непроверенное ребро из четной вершины
:- Выберем любое непроверенное ребро
- Вершина нечетное - ничего не делаем. Такая ситуация возникает, когда ребро из паросочетания или не из паросочетания
- Вершина включено в паросочетание и непосещенное. Тогда помечаем нечетным, а четным. Присваиваем , а также
- четное; вершины лежат в разных деревьях - нашли удлиняющий путь от корня дерева, содержащего вершину до корня дерева, содержащего вершину .
- четное; вершины лежат в одном дереве - нашли соцветие. Пусть - наименьший общий предок вершин и . Сожмем соцветие в псевдо-вершину , , а также для каждой вершины в соцветии определим
из четной вершины и проверяем:
Псевдокод
Edmonds { forif (вершина u не в паросочетании) { int last_v = find_augment_path (u); if (last_v != -1) выполнить чередование вдоль пути из u в last_v; } } int find_augment_path (root) { обход в ширину: v = текущая_вершина; for если обнаружили цикл нечётной длины, сжать его если пришли в свободную вершину, return если пришли в несвободную вершину, то добавить в очередь смежную ей в паросочетании return -1; }