Как доказать корректность алгоритма Куна через теорему Бержа об увеличивающих путях?
Алгоритм Куна я запрограммировал, он работает. Но на устном этапе/в разборе нужно доказать, что он даёт именно максимальное паросочетание. Все ссылаются на «теорему Бержа об увеличивающих путях». Как звучит теорема и как из неё следует корректность Куна?
2 ответа
Увеличивающий путь для паросочетания — это простой путь, который начинается и заканчивается в непокрытых (свободных) вершинах и чередует рёбра «не в / в / не в / ...». Если такой путь есть, его можно «инвертировать» (поменять статус каждого ребра вдоль пути) — рёбер из станет на 1 больше.
Теорема Бержа: паросочетание максимально тогда и только тогда, когда в графе нет увеличивающего пути относительно .
Набросок доказательства. () Если увеличивающий путь есть, инвертируем его и получаем большее паросочетание — значит не было максимальным. () Пусть не максимально, и есть большее . Рассмотрим симметрическую разность — она состоит из путей и циклов, где рёбра и чередуются. Так как , найдётся путь, где рёбер больше — а это и есть увеличивающий путь относительно . Противоречие.
Корректность Куна. Кун, обрабатывая левые вершины по очереди, для каждой ищет увеличивающий путь (DFS, чередующий свободные рёбра и рёбра паросочетания). Он находит увеличивающий путь всякий раз, когда тот существует для текущей вершины. По завершении внешнего цикла ни для одной свободной левой вершины увеличивающего пути нет → по Бержу паросочетание максимально.
Ключевой факт, почему достаточно одного прохода по левым вершинам: однажды покрытая левая вершина остаётся покрытой до конца (паросочетание только растёт), поэтому пересматривать её не нужно.
Тонкий момент, который часто спрашивают на устном: почему DFS Куна корректно ищет именно чередующийся путь, хотя в коде нет явного «чередования»? Потому что переход из левой вершины идёт по свободному ребру в правую , а дальше — рекурсивный вызов tryKuhn(matchR[r]), то есть мы идём по ребру паросочетания от обратно в левую долю. Так автоматически выдерживается «свободное → matched → свободное → ...». Когда доходим до свободной правой вершины (matchR[r]==-1) — путь увеличивающий, инвертируем его рекурсивным присваиванием matchR[r]=v вдоль возврата из рекурсии.