<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=188.232.142.138&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=188.232.142.138&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/188.232.142.138"/>
		<updated>2026-05-20T08:18:45Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9A%D1%83%D0%BD%D0%B0_%D0%B4%D0%BB%D1%8F_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=44791</id>
		<title>Алгоритм Куна для поиска максимального паросочетания</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9A%D1%83%D0%BD%D0%B0_%D0%B4%D0%BB%D1%8F_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=44791"/>
				<updated>2015-02-04T10:50:36Z</updated>
		
		<summary type="html">&lt;p&gt;188.232.142.138: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Теорема==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
 Если из вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; не существует [[Теорема о максимальном паросочетании и дополняющих цепях|дополняющей цепи]] относительно паросочетания &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; и паросочетание &amp;lt;tex&amp;gt;M'&amp;lt;/tex&amp;gt; получается из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; изменением вдоль дополняющей цепи, тогда из &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; не существует дополняющей цепи в &amp;lt;tex&amp;gt;M'&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
[[Файл:Kuhn2.png|thumb|right|300x300px|Рисунок 1.]]&lt;br /&gt;
[[Файл:Kuhn1.png|thumb|right|300x300px|Рисунок 2.&amp;lt;br&amp;gt;Пунктиром обозначен путь между двумя вершинами. Ребро красного цвета лежит в паросочетании, а черного - нет.]]&lt;br /&gt;
: Доказательство от противного.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: Допустим в паросочетание внесли изменения вдоль дополняющей цепи &amp;lt;tex&amp;gt;(y \rightsquigarrow z)&amp;lt;/tex&amp;gt; и из вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; появилась дополняющая цепь.&lt;br /&gt;
: Заметим, что эта дополняющая цепь должна вершинно пересекаться с той цепью, вдоль которой вносились изменения, иначе такая же дополняющая цепь из &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; существовала и в исходном паросочетании.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: Пусть &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; – ближайшая к &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; вершина, которая принадлежит и новой дополняющей цепи и цепи &amp;lt;tex&amp;gt;(y \rightsquigarrow z)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
: Тогда &amp;lt;tex&amp;gt;MP&amp;lt;/tex&amp;gt; – последнее ребро на отрезке &amp;lt;tex&amp;gt;(y \rightsquigarrow p)&amp;lt;/tex&amp;gt; цепи &amp;lt;tex&amp;gt;(y \rightsquigarrow z)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;NP&amp;lt;/tex&amp;gt; – последнее ребро на отрезке &amp;lt;tex&amp;gt;(z \rightsquigarrow p)&amp;lt;/tex&amp;gt; цепи &amp;lt;tex&amp;gt;(y \rightsquigarrow z)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;QP&amp;lt;/tex&amp;gt; - последнее ребро лежащее на отрезке &amp;lt;tex&amp;gt;(x \rightsquigarrow p)&amp;lt;/tex&amp;gt; новой дополняющей цепи(см. Рисунок 1).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: Допустим &amp;lt;tex&amp;gt;MP&amp;lt;/tex&amp;gt; принадлежит паросочетанию &amp;lt;tex&amp;gt;M'&amp;lt;/tex&amp;gt;, тогда &amp;lt;tex&amp;gt;NP&amp;lt;/tex&amp;gt; ему не принадлежит.&amp;lt;br&amp;gt;&lt;br /&gt;
:: (Случай, когда &amp;lt;tex&amp;gt;NP&amp;lt;/tex&amp;gt; принадлежит паросочетанию &amp;lt;tex&amp;gt;M'&amp;lt;/tex&amp;gt; полностью симметричен.)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: Поскольку паросочетание &amp;lt;tex&amp;gt;M'&amp;lt;/tex&amp;gt; получается из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; изменением вдоль дополняющей цепи &amp;lt;tex&amp;gt;(y \rightsquigarrow z)&amp;lt;/tex&amp;gt;, в паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; входило ребро &amp;lt;tex&amp;gt;NP&amp;lt;/tex&amp;gt;, а ребро &amp;lt;tex&amp;gt;MP&amp;lt;/tex&amp;gt; нет.&lt;br /&gt;
: Кроме того, ребро &amp;lt;tex&amp;gt;QP&amp;lt;/tex&amp;gt; не лежит ни в исходном паросочетании &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, ни в паросочетании &amp;lt;tex&amp;gt;M'&amp;lt;/tex&amp;gt;, в противном случае оказалось бы, что вершина &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; инцидентна нескольким ребрам из паросочетания, что противоречит определению паросочетания.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:Тогда заметим, что цепь &amp;lt;tex&amp;gt;(x \rightsquigarrow z)&amp;lt;/tex&amp;gt;, полученная объединением цепей &amp;lt;tex&amp;gt;(x \rightsquigarrow p)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;(p \rightsquigarrow z)&amp;lt;/tex&amp;gt;, по определению будет дополняющей в паросочетании &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, что приводит к противоречию, поскольку в паросочетании &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; из вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; не существует дополняющей цепи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
Задан граф &amp;lt;tex&amp;gt;G\langle V, E \rangle&amp;lt;/tex&amp;gt;, про который известно, что он двудольный, но разбиение не задано явно.Требуется найти наибольшее паросочетание в нем&lt;br /&gt;
&lt;br /&gt;
Алгоритм можно описать так: сначала возьмём пустое паросочетание, а потом — пока в графе удаётся найти увеличивающую цепь, — будем выполнять чередование паросочетания вдоль этой цепи, и повторять процесс поиска увеличивающей цепи. Как только такую цепь найти не удалось — процесс останавливаем, — текущее паросочетание и есть максимальное.&lt;br /&gt;
&lt;br /&gt;
В массиве &amp;lt;tex&amp;gt;\mathtt{matching}&amp;lt;/tex&amp;gt; хранятся паросочетания &amp;lt;tex&amp;gt; (v, \mathtt{matching}[v]) &amp;lt;/tex&amp;gt;  (Если паросочетания с вершиной &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; не существует, то &amp;lt;tex&amp;gt; \mathtt{matching}[v]= -1&amp;lt;/tex&amp;gt;). А &amp;lt;tex&amp;gt;used&amp;lt;/tex&amp;gt; — обычный массив &amp;quot;посещённостей&amp;quot; вершин в обходе в глубину (он нужен, чтобы обход в глубину не заходил в одну вершину дважды).&lt;br /&gt;
Функция &amp;lt;tex&amp;gt; \mathrm{dfs} &amp;lt;/tex&amp;gt; возвращает  &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;, если ей удалось найти увеличивающую цепь из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, при этом считается, что эта функция уже произвела чередование паросочетания вдоль найденной цепи.&lt;br /&gt;
&lt;br /&gt;
Внутри функции просматриваются все рёбра, исходящие из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, и затем проверяется: если это ребро ведёт в ненасыщенную вершину &amp;lt;tex&amp;gt; to&amp;lt;/tex&amp;gt;, либо если эта вершина &amp;lt;tex&amp;gt;to&amp;lt;/tex&amp;gt; насыщена, но удаётся найти увеличивающую цепь рекурсивным запуском из &amp;lt;tex&amp;gt;\mathtt{matching}[to]&amp;lt;/tex&amp;gt;, то мы говорим, что мы нашли увеличивающую цепь, и перед возвратом из функции с результатом &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt; производим чередование в текущем ребре: перенаправляем ребро, смежное с &amp;lt;tex&amp;gt;to&amp;lt;/tex&amp;gt;, в вершину &amp;lt;tex&amp;gt; v&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В основной программе сначала указывается, что текущее паросочетание — пустое (массив &amp;lt;tex&amp;gt; \mathtt{matching}&amp;lt;/tex&amp;gt; заполняется числами &amp;lt;tex&amp;gt;-1&amp;lt;/tex&amp;gt;). Затем перебирается вершина  &amp;lt;tex&amp;gt;v &amp;lt;/tex&amp;gt;, и из неё запускается обход в глубину &amp;lt;tex&amp;gt; \mathrm{dfs} &amp;lt;/tex&amp;gt;, предварительно обнулив массив &amp;lt;tex&amp;gt; used&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что размер паросочетания легко получить как число вызовов &amp;lt;tex&amp;gt; \mathrm{dfs} &amp;lt;/tex&amp;gt; в основной программе, вернувших результат &amp;lt;tex&amp;gt; true &amp;lt;/tex&amp;gt;. Само искомое максимальное паросочетание содержится в массиве &amp;lt;tex&amp;gt; \mathtt{matching}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
После того, как все вершины &amp;lt;tex&amp;gt;v \in V&amp;lt;/tex&amp;gt; будут просмотрены, текущее паросочетание будет максимальным.&lt;br /&gt;
Корректность алгоритма следует из [[Теорема о максимальном паросочетании и дополняющих цепях|теоремы о максимальном паросочетании и дополняющих цепях]] и теоремы, описанной выше.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
&lt;br /&gt;
* Граф &amp;lt;tex&amp;gt;G\langle V, E \rangle&amp;lt;/tex&amp;gt; хранится в матрице смежности &amp;lt;tex&amp;gt;g[i][j]&amp;lt;/tex&amp;gt; размера &amp;lt;tex&amp;gt;n &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;n  = |V|&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 '''bool''' dfs(v: '''int'''):&lt;br /&gt;
     '''if''' (used[v])&lt;br /&gt;
         '''return''' ''false''&lt;br /&gt;
     used[v] = ''true''&lt;br /&gt;
     '''for''' to '''in''' g[v]&lt;br /&gt;
         '''if''' (matching[to] == -1 '''or''' dfs(matching[to])):&lt;br /&gt;
             matching[to] = v&lt;br /&gt;
             '''return''' ''true'' &lt;br /&gt;
     '''return''' ''false''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 function '''main'''():&lt;br /&gt;
     fill(matching, -1)&lt;br /&gt;
     '''for''' i = 1..n&lt;br /&gt;
          fill(used, ''false'')&lt;br /&gt;
          dfs(i)&lt;br /&gt;
     '''for''' i = 1..n&lt;br /&gt;
          '''if''' (matching[i] != -1)&lt;br /&gt;
               print(i, &amp;quot; &amp;quot;, matching[i])&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
:Итак, алгоритм Куна можно представить как серию из  &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; запусков обхода в глубину на всём графе.&lt;br /&gt;
:Следовательно, всего этот алгоритм исполняется за время &amp;lt;tex&amp;gt;O(nm)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; {{---}} количество ребер, что в худшем случае есть &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;&lt;br /&gt;
:Если явно задано разбиение графа на две доли размером &amp;lt;tex&amp;gt;n_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n_2&amp;lt;/tex&amp;gt;, то можно запускать &amp;lt;tex&amp;gt;\mathtt{dfs}&amp;lt;/tex&amp;gt; только из вершин первой доли, поэтому весь алгоритм исполняется за время &amp;lt;tex&amp;gt;O(n_1m)&amp;lt;/tex&amp;gt;.  В худшем случае это составляет &amp;lt;tex&amp;gt;O(n_1^2n_2).&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
* [[Теорема_о_максимальном_паросочетании_и_дополняющих_цепях|Теорема о максимальном паросочетании и дополняющих цепях]]&lt;br /&gt;
* [[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Алгоритм Форда-Фалкерсона для поиска максимального паросочетания]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
*[http://e-maxx.ru/algo/kuhn_matching MAXimal :: algo :: Алгоритм Куна нахождения наибольшего паросочетания]&amp;lt;br&amp;gt;&lt;br /&gt;
* Асанов М., Баранский В., Расин В. {{---}} Дискретная математика: Графы, матроиды, алгоритмы — СПб.: Издательство &amp;quot;Лань&amp;quot;, 2010. — 291 стр.&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.232.142.138</name></author>	</entry>

	</feed>