<?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=Da1s111</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=Da1s111"/>
		<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/Da1s111"/>
		<updated>2026-06-11T20:17:38Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52081</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52081"/>
				<updated>2016-01-28T19:49:37Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Базовые определения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть множество вершин графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; разбито на взаимно дополнительные подмножества &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Через &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; обозначим множество всех ребер графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, у каждого из которых один конец лежит в &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt;, а другой {{---}} в &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Так как торцевые графы являются деревьями, то:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |V(X)| = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют степени, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52080</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52080"/>
				<updated>2016-01-28T19:48:37Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть множество вершин графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; разбито на взаимно дополнительные подмножества &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Через &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; обозначим множество всех ребер графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, у каждого из которых один конец лежит в &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt;, а другой {{---}} в &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Так как торцевые графы являются деревьями, то:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |V(X)| = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют степени, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52079</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52079"/>
				<updated>2016-01-28T19:47:32Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Теорема Гринберга */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть множество вершин графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; разбито на взаимно дополнительные подмножества &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Через &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; обозначим множество всех ребер графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, у каждого из которых один конец лежит в &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt;, а другой {{---}} в &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Так как торцевые графы являются деревьями, то:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |V(X)| = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют степени, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52077</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52077"/>
				<updated>2016-01-28T19:28:14Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Базовые определения и теоремы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть множество вершин графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; разбито на взаимно дополнительные подмножества &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Через &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; обозначим множество всех ребер графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, у каждого из которых один конец лежит в &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt;, а другой {{---}} в &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''2''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют степени, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52076</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52076"/>
				<updated>2016-01-28T19:10:52Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Базовые определения и теоремы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' (англ. ''cyclomatic number'') графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего ''соотношения'':&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) ~~~ \textbf{(1)} &amp;lt;/tex&amp;gt; &amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' (англ. ''Betti number'') размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt;. Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется. Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1. Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=2&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Пусть множество вершин графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; разбито на взаимно дополнительные подмножества &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Через &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; обозначим множество всех ребер графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, у каждого из которых один конец лежит в &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt;, а другой {{---}} в &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''2''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют степени, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52074</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52074"/>
				<updated>2016-01-28T19:04:03Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Использование теоремы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' (англ. ''cyclomatic number'') графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего ''соотношения'':&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) ~~~ \textbf{(1)} &amp;lt;/tex&amp;gt; &amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' (англ. ''Betti number'') размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt;. Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется. Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1. Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=2&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''2''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют степени, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52073</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52073"/>
				<updated>2016-01-28T19:03:40Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Теорема Гринберга */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' (англ. ''cyclomatic number'') графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего ''соотношения'':&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) ~~~ \textbf{(1)} &amp;lt;/tex&amp;gt; &amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' (англ. ''Betti number'') размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt;. Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется. Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1. Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=2&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; степень &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''2''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют валентности, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52071</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52071"/>
				<updated>2016-01-28T19:01:14Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Базовые определения и теоремы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' (англ. ''cyclomatic number'') графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего ''соотношения'':&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) ~~~ \textbf{(1)} &amp;lt;/tex&amp;gt; &amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' (англ. ''Betti number'') размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt;. Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется. Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1. Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=2&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Подграф''' (англ. ''subgraph'') исходного графа {{---}} граф, содержащий некое подмножество вершин данного графа и некое подмножество инцидентных им рёбер. По отношению к подграфу исходный граф называется суперграфом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порождённый подграф''' (англ. ''induced subgraph'') — подграф, порождённый множеством рёбер исходного графа. Содержит не обязательно все вершины графа, но эти вершины соединены такими же ребрами, как в графе.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' (англ. ''hamiltonian bond'') называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число и вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; валентность &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''1.37''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют валентности, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52044</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52044"/>
				<updated>2016-01-28T18:07:36Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Теорема Гринберга */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего соотношения:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) &amp;lt;/tex&amp;gt;. '''(1.6.1)'''&amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.35&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt; (в силу соотношения '''1.6.1''' и теоремы '''1.20'''). Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется (см. теоремы '''1.32''' и '''1.34'''). Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1 (см. теорему '''1.34'''). Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.37&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1.35''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1.6.1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число и вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; валентность &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 ~~~ \bf{(1)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''1.37''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 ~~~ \textbf{(2)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| ~~~ \textbf{(3)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 ~~~ \textbf{(4)} &amp;lt;/tex&amp;gt;. &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют валентности, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52037</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52037"/>
				<updated>2016-01-28T18:01:53Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего соотношения:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) &amp;lt;/tex&amp;gt;. '''(1.6.1)'''&amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.35&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt; (в силу соотношения '''1.6.1''' и теоремы '''1.20'''). Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется (см. теоремы '''1.32''' и '''1.34'''). Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1 (см. теорему '''1.34'''). Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.37&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1.35''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1.6.1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число и вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; валентность &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 &amp;lt;/tex&amp;gt;. '''(1)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''1.37''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 &amp;lt;/tex&amp;gt;. '''(2)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| &amp;lt;/tex&amp;gt;. '''(3)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 &amp;lt;/tex&amp;gt;. '''(4)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют валентности, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52033</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52033"/>
				<updated>2016-01-28T17:48:02Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Теорема Гринберга */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего соотношения:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) &amp;lt;/tex&amp;gt;. '''(1.6.1)'''&amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.35&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt; (в силу соотношения '''1.6.1''' и теоремы '''1.20'''). Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется (см. теоремы '''1.32''' и '''1.34'''). Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1 (см. теорему '''1.34'''). Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.37&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1.35''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1.6.1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} число и вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; валентность &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 &amp;lt;/tex&amp;gt;. '''(1)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''1.37''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 &amp;lt;/tex&amp;gt;. '''(2)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| &amp;lt;/tex&amp;gt;. '''(3)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 &amp;lt;/tex&amp;gt;. '''(4)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют валентности, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
[[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52031</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52031"/>
				<updated>2016-01-28T17:46:05Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего соотношения:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) &amp;lt;/tex&amp;gt;. '''(1.6.1)'''&amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также '''числом Бетти''' размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.35&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt; (в силу соотношения '''1.6.1''' и теоремы '''1.20'''). Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; ребра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется (см. теоремы '''1.32''' и '''1.34'''). Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1 (см. теорему '''1.34'''). Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.37&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1.35''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1.6.1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} числои вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; валентность &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 &amp;lt;/tex&amp;gt;. '''(1)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''1.37''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 &amp;lt;/tex&amp;gt;. '''(2)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| &amp;lt;/tex&amp;gt;. '''(3)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 &amp;lt;/tex&amp;gt;. '''(4)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Использование теоремы ==&lt;br /&gt;
Теорему Гринберга можно иногда использовать для доказательства отсутствия гамильтонова бонда в графе. Пусть, например, все вершины связного графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, кроме одной, имеют валентности, сравнимые с 2 по модулю 3. Тогда левая часть формулы '''(1)''' не делится на 3 и, следовательно, гамильтонова бонда в графе &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не существует. Рисунок '''1''' иллюстрирует этот простой пример.&lt;br /&gt;
[[Файл: Гамильтонов_бонд.png|300px|thumb|center|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
[[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%93%D0%B0%D0%BC%D0%B8%D0%BB%D1%8C%D1%82%D0%BE%D0%BD%D0%BE%D0%B2_%D0%B1%D0%BE%D0%BD%D0%B4.png&amp;diff=52028</id>
		<title>Файл:Гамильтонов бонд.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%93%D0%B0%D0%BC%D0%B8%D0%BB%D1%8C%D1%82%D0%BE%D0%BD%D0%BE%D0%B2_%D0%B1%D0%BE%D0%BD%D0%B4.png&amp;diff=52028"/>
				<updated>2016-01-28T17:40:06Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: Пример док-ва отсутствия гамильтонова бонда в графе.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Пример док-ва отсутствия гамильтонова бонда в графе.&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52020</id>
		<title>Теорема Гринберга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%93%D1%80%D0%B8%D0%BD%D0%B1%D0%B5%D1%80%D0%B3%D0%B0&amp;diff=52020"/>
				<updated>2016-01-28T17:29:20Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Базовые определения и теоремы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Цикломатическое число''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; обозначается через &amp;lt;tex&amp;gt; p_1(G) &amp;lt;/tex&amp;gt; и определяется с помощью следующего соотношения:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; p_1(G) = |E(G)| - |V(G)| + p_0(G) &amp;lt;/tex&amp;gt;. '''(1.6.1)'''&amp;lt;/center&amp;gt;&lt;br /&gt;
Это число называют также числом Бетти размерности 1.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.35&lt;br /&gt;
|statement=&lt;br /&gt;
Цикломатическое число графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; неотрицательно. Оно равно нулю тогда и только тогда, когда &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; {{---}} лес.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим сначала, что в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; нет ребер. Тогда &amp;lt;tex&amp;gt; p_1(G) = 0 &amp;lt;/tex&amp;gt; (в силу соотношения '''1.6.1''' и теоремы '''1.20'''). Очевидно, что &amp;quot;безреберный&amp;quot; граф является лесом.&lt;br /&gt;
Далее предположим, что граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; есть лес и в нем содержится хотя бы одно ребро. Удаляем из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; рбра до тех пор, пока не получим безреберного графа &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt;. При удалении каждого ребра цикломатическое число не меняется (см. теоремы '''1.32''' и '''1.34'''). Следовательно, &amp;lt;tex&amp;gt; p_1(G) = p_1(H) = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Наконец, рассмотрим случай, когда граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; не является лесом. Тогда в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; содержится ребро &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, не являющееся перешейком. Удаляя его из &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, мы уменьшим цикломатическое число на 1 (см. теорему '''1.34'''). Если результирующий граф не будет лесом, то процесс удаления ребра повторяем. После нескольких таких шагов (обозначим их число через &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;) мы получим лес &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;. Очевидно, что &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} положительное число, и мы имеем &amp;lt;tex&amp;gt; p_1(G) = n + p_1(F) = n &amp;gt; 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=1.37&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; {{---}} дерево, то &amp;lt;tex&amp;gt; |V(T)| = |E(T)| + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Имеем &amp;lt;tex&amp;gt; p_0(T) = 1 &amp;lt;/tex&amp;gt;. По теореме '''1.35''': &amp;lt;tex&amp;gt; p_1(T) = 0 &amp;lt;/tex&amp;gt;. Остается применить соотношение '''1.6.1'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; и порожденные подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; связны, то множество &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; называется '''бондом''' графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Подграфы &amp;lt;tex&amp;gt; G[X] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; G[Y] &amp;lt;/tex&amp;gt; называются '''торцевыми графами''' этого бонда. Из приведенного определения следует, что бонд &amp;lt;tex&amp;gt; J(X, Y) &amp;lt;/tex&amp;gt; должен быть непустым множеством. Если граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; несвязен, то его '''бонд''' определим как бонд какой-либо его компоненты. Заметим, что всякий перешеек графа образует однореберный бонд. Торцевые графы перешейка являются торцевыми графами соответствующего бонда.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Гамильтоновым бондом''' называется бонд графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;, торцевыми графами которого являются деревья, т.е. бонд, состоящий из &amp;lt;tex&amp;gt; p_1(G) + 1 &amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Теорема Гринберга ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Гринберг&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть связный граф &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; имеет гамильтонов бонд &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; с торцевыми графами &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; f_n^{X} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; f_n^{Y} &amp;lt;/tex&amp;gt; {{---}} числои вершин в графов &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, имеющих в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt; валентность &amp;lt;tex&amp;gt; n ~ (n = 1, ~ 2, ~ 3, ~ \ldots) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) (f_n^{X} - f_n^{Y}) = 0 &amp;lt;/tex&amp;gt;. '''(1)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Используя теорему '''1.37''', находим, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} f_n^{X} = |E(X)| + 1 &amp;lt;/tex&amp;gt;. '''(2)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Ясно также, что:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} n f_n^{X} = |E(H)| + 2|E(X)| &amp;lt;/tex&amp;gt;. '''(3)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Поэтому:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; \sum\limits_{n=1}^{\infty} (n - 2) f_n^{X} = |E(H)| - 2 &amp;lt;/tex&amp;gt;. '''(4)''' &amp;lt;/center&amp;gt;&lt;br /&gt;
Аналогичную формулу получаем для графа &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. Вычитая ее из '''(4)''', приходим к '''(1)'''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
[[Гамильтоновы графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* У. Татт. Теория графов. М.: &amp;quot;Мир&amp;quot;, 1988. с. 304. ISBN 5-03-001001-7&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Обходы графов]]&lt;br /&gt;
[[Категория:Гамильтоновы графы]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51909</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51909"/>
				<updated>2016-01-27T19:17:41Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Время работы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
* Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
* Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
* Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
** Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
** В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
: Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица &amp;lt;/center&amp;gt;&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a. &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Ключевые идеи ===&lt;br /&gt;
* Для проверки наличия увеличивающей цепочки нет необходимости запускать обход Куна заново после каждого пересчёта потенциала. Вместо этого можно оформить [[Алгоритм Куна для поиска максимального паросочетания|обход Куна]] в итеративном виде: после каждого пересчёта потенциала мы просматриваем добавившиеся жёсткие рёбра и, если их левые концы были достижимыми, помечаем их правые концы также как достижимые и продолжаем обход из них.&lt;br /&gt;
* Развивая эту идею дальше, можно прийти к такому представлению алгоритма: это цикл, на каждом шаге которого сначала пересчитывается потенциал, затем находится столбец, ставший достижимым (а таковой всегда найдётся, поскольку после пересчёта потенциала всегда появляются новые достижимые вершины), и если этот столбец был ненасыщен, то найдена увеличивающая цепь, а если столбец был насыщен — то соответствующая ему в паросочетании строка также становится достижимой.&lt;br /&gt;
* Теперь алгоритм принимает вид: цикл добавления столбцов, на каждом из которых сначала пересчитывается потенциал, а затем какой-то новый столбец помечается как достижимый.&lt;br /&gt;
* Чтобы быстро пересчитывать потенциал (быстрее, чем наивный вариант за &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;), надо поддерживать вспомогательные минимумы по каждому из столбцов &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], ~ v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца &amp;lt;tex&amp;gt; \mathtt{j} &amp;lt;/tex&amp;gt; вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \mathtt{Z_1} &amp;lt;/tex&amp;gt; {{---}} множество вершин первой доли, которые были посещены обходом [[Алгоритм Куна для поиска максимального паросочетания|алгоритма Куна]] при попытке поиска увеличивающей цепи.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n &amp;lt;font color=darkgreen&amp;gt;// рассматриваем строки матрицы ''a'' &amp;lt;/font&amp;gt;&lt;br /&gt;
     p[0] = i &amp;lt;font color=darkgreen&amp;gt;// для удобства реализации &amp;lt;/font&amp;gt;&lt;br /&gt;
     j0 = 0 &amp;lt;font color=darkgreen&amp;gt;// свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
       used[j0] = ''true'', i0 = p[j0] &amp;lt;font color=darkgreen&amp;gt;// помечаем посещенными столбец ''j0'' и строку ''i0'' &amp;lt;/font&amp;gt;&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' (изначально ''&amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;'') и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       '''for''' j = 0 '''to''' m &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv'' &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; minv &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51907</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51907"/>
				<updated>2016-01-27T19:10:14Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
* Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
* Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
* Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
** Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
** В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
: Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица &amp;lt;/center&amp;gt;&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a. &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Ключевые идеи ===&lt;br /&gt;
* Для проверки наличия увеличивающей цепочки нет необходимости запускать обход Куна заново после каждого пересчёта потенциала. Вместо этого можно оформить [[Алгоритм Куна для поиска максимального паросочетания|обход Куна]] в итеративном виде: после каждого пересчёта потенциала мы просматриваем добавившиеся жёсткие рёбра и, если их левые концы были достижимыми, помечаем их правые концы также как достижимые и продолжаем обход из них.&lt;br /&gt;
* Развивая эту идею дальше, можно прийти к такому представлению алгоритма: это цикл, на каждом шаге которого сначала пересчитывается потенциал, затем находится столбец, ставший достижимым (а таковой всегда найдётся, поскольку после пересчёта потенциала всегда появляются новые достижимые вершины), и если этот столбец был ненасыщен, то найдена увеличивающая цепь, а если столбец был насыщен — то соответствующая ему в паросочетании строка также становится достижимой.&lt;br /&gt;
* Теперь алгоритм принимает вид: цикл добавления столбцов, на каждом из которых сначала пересчитывается потенциал, а затем какой-то новый столбец помечается как достижимый.&lt;br /&gt;
* Чтобы быстро пересчитывать потенциал (быстрее, чем наивный вариант за &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;), надо поддерживать вспомогательные минимумы по каждому из столбцов &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], ~ v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца &amp;lt;tex&amp;gt; \mathtt{j} &amp;lt;/tex&amp;gt; вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \mathtt{Z_1} &amp;lt;/tex&amp;gt; {{---}} множество вершин первой доли, которые были посещены обходом [[Алгоритм Куна для поиска максимального паросочетания|алгоритма Куна]] при попытке поиска увеличивающей цепи.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n &amp;lt;font color=darkgreen&amp;gt;// рассматриваем строки матрицы ''a'' &amp;lt;/font&amp;gt;&lt;br /&gt;
     p[0] = i &amp;lt;font color=darkgreen&amp;gt;// для удобства реализации &amp;lt;/font&amp;gt;&lt;br /&gt;
     j0 = 0 &amp;lt;font color=darkgreen&amp;gt;// свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
       used[j0] = ''true'', i0 = p[j0] &amp;lt;font color=darkgreen&amp;gt;// помечаем посещенными столбец ''j0'' и строку ''i0'' &amp;lt;/font&amp;gt;&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' (изначально ''&amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;'') и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       '''for''' j = 0 '''to''' m &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv'' &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51906</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51906"/>
				<updated>2016-01-27T18:56:35Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
* Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
* Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
* Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
** Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
** В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
**Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие: &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], ~ v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца &amp;lt;tex&amp;gt; \mathtt{j} &amp;lt;/tex&amp;gt; вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \mathtt{Z_1} &amp;lt;/tex&amp;gt; {{---}} множество вершин первой доли, которые были посещены обходом [[Алгоритм Куна для поиска максимального паросочетания|алгоритма Куна]] при попытке поиска увеличивающей цепи.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n &amp;lt;font color=darkgreen&amp;gt;// рассматриваем строки матрицы ''a'' &amp;lt;/font&amp;gt;&lt;br /&gt;
     p[0] = i &amp;lt;font color=darkgreen&amp;gt;// для удобства реализации &amp;lt;/font&amp;gt;&lt;br /&gt;
     j0 = 0 &amp;lt;font color=darkgreen&amp;gt;// свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
       used[j0] = ''true'', i0 = p[j0] &amp;lt;font color=darkgreen&amp;gt;// помечаем посещенными столбец ''j0'' и строку ''i0'' &amp;lt;/font&amp;gt;&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' (изначально ''&amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;'') и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       '''for''' j = 0 '''to''' m &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv'' &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51905</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51905"/>
				<updated>2016-01-27T18:51:44Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Общий метод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
* Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
* Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
* Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
** Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
** В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], ~ v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца &amp;lt;tex&amp;gt; \mathtt{j} &amp;lt;/tex&amp;gt; вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \mathtt{Z_1} &amp;lt;/tex&amp;gt; {{---}} множество вершин первой доли, которые были посещены обходом [[Алгоритм Куна для поиска максимального паросочетания|алгоритма Куна]] при попытке поиска увеличивающей цепи.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n &amp;lt;font color=darkgreen&amp;gt;// рассматриваем строки матрицы ''a'' &amp;lt;/font&amp;gt;&lt;br /&gt;
     p[0] = i &amp;lt;font color=darkgreen&amp;gt;// для удобства реализации &amp;lt;/font&amp;gt;&lt;br /&gt;
     j0 = 0 &amp;lt;font color=darkgreen&amp;gt;// свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
       used[j0] = ''true'', i0 = p[j0] &amp;lt;font color=darkgreen&amp;gt;// помечаем посещенными столбец ''j0'' и строку ''i0'' &amp;lt;/font&amp;gt;&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' (изначально ''&amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;'') и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       '''for''' j = 0 '''to''' m &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv'' &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51904</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51904"/>
				<updated>2016-01-27T18:43:51Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], ~ v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца &amp;lt;tex&amp;gt; \mathtt{j} &amp;lt;/tex&amp;gt; вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \mathtt{Z_1} &amp;lt;/tex&amp;gt; {{---}} множество вершин первой доли, которые были посещены обходом [[Алгоритм Куна для поиска максимального паросочетания|алгоритма Куна]] при попытке поиска увеличивающей цепи.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n &amp;lt;font color=darkgreen&amp;gt;// рассматриваем строки матрицы ''a'' &amp;lt;/font&amp;gt;&lt;br /&gt;
     p[0] = i &amp;lt;font color=darkgreen&amp;gt;// для удобства реализации &amp;lt;/font&amp;gt;&lt;br /&gt;
     j0 = 0 &amp;lt;font color=darkgreen&amp;gt;// свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец &amp;lt;/font&amp;gt;&lt;br /&gt;
       used[j0] = ''true'', i0 = p[j0] &amp;lt;font color=darkgreen&amp;gt;// помечаем посещенными столбец ''j0'' и строку ''i0'' &amp;lt;/font&amp;gt;&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' (изначально ''&amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;'') и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       '''for''' j = 0 '''to''' m &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv'' &amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51898</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51898"/>
				<updated>2016-01-26T19:40:51Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], ~ v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n // рассматриваем строки матрицы ''a''&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' // ищем свободный столбец&lt;br /&gt;
       помечаем посещенными столбец ''j0'' и строку ''i0''&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv''&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51897</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51897"/>
				<updated>2016-01-26T19:38:34Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Время работы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n // рассматриваем строки матрицы ''a''&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' // ищем свободный столбец&lt;br /&gt;
       помечаем посещенными столбец ''j0'' и строку ''i0''&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv''&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51896</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51896"/>
				<updated>2016-01-26T19:37:54Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} потенциал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n // рассматриваем строки матрицы ''a''&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' // ищем свободный столбец&lt;br /&gt;
       помечаем посещенными столбец ''j0'' и строку ''i0''&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       производим пересчет потенциала ''u'' и ''v'', соответствующее изменение ''minv''&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51895</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51895"/>
				<updated>2016-01-26T19:30:41Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Время работы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n // рассматриваем строки матрицы ''a''&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' // ищем свободный столбец&lt;br /&gt;
       помечаем посещенными столбец ''j0'' и строку ''i0''&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       производим пересчет потенциалов ''u'' и ''v'' и соответствующее изменение ''minv''&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; [[Алгоритм Куна для поиска максимального паросочетания|алгоритм Куна]] суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51894</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51894"/>
				<updated>2016-01-26T19:30:00Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &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;
* '''Шаг 0.''' Введем ''следующее понятие'':&lt;br /&gt;
** Назовём потенциалом два произвольных массива чисел &amp;lt;tex&amp;gt; u[1 \ldots n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; v[1 \ldots n] &amp;lt;/tex&amp;gt; таких, что выполняется условие:&lt;br /&gt;
 &amp;lt;tex&amp;gt; u[i] + v[j] \leqslant a[i][j] ~ (i = 1 \ldots n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; {{---}} заданная матрица&lt;br /&gt;
* '''Шаг 1.''' Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;&lt;br /&gt;
* '''Шаг 2.''' Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* '''Шаг 3.''' Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n // рассматриваем строки матрицы ''a''&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' // ищем свободный столбец&lt;br /&gt;
       помечаем посещенными столбец ''j0'' и строку ''i0''&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       производим пересчет потенциалов ''u'' и ''v'' и соответствующее изменение ''minv''&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; алгоритм Куна суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51893</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51893"/>
				<updated>2016-01-26T19:12:55Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Общая идея ===&lt;br /&gt;
Будем добавлять в рассмотрение строки матрицы одну за одной, а не рассматривать их все сразу.&lt;br /&gt;
&lt;br /&gt;
=== Описание алгоритма ===&lt;br /&gt;
* Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; \mathtt{a} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt; \mathtt{0} &amp;lt;/tex&amp;gt;, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[j] = \min\limits_{i \in Z_1}(a[i][j] - u[i] - v[j])} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n // рассматриваем строки матрицы ''a''&lt;br /&gt;
     заполняем массивы ''minv'' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, ''used'' {{---}} ''false''&lt;br /&gt;
     '''while''' ''true'' // ищем свободный столбец&lt;br /&gt;
       помечаем посещенными столбец ''j0'' и строку ''i0''&lt;br /&gt;
       пересчитываем массив ''minv'', находим в нем минимум ''&amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;'' и столбец ''j1'', в котором он достигнут&lt;br /&gt;
       производим пересчет потенциалов ''u'' и ''v'' и соответствующее изменение ''minv''&lt;br /&gt;
       если нашли свободный столбец {{---}} выходим из цикла&lt;br /&gt;
     ищем увеличивающуюся цепочку, пользуясь массивом предков ''way''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; алгоритм Куна суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51892</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51892"/>
				<updated>2016-01-26T18:18:05Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Венгерский алгоритм''''' (англ. ''Hungarian algorithm'') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Общая идея ===&lt;br /&gt;
Будем добавлять в рассмотрение строки матрицы одну за одной, а не рассматривать их все сразу.&lt;br /&gt;
&lt;br /&gt;
=== Описание алгоритма ===&lt;br /&gt;
* Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; \mathtt{a} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt; \mathtt{minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     заполняем массивы '''minv''' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, '''used''' {{---}} false&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m&lt;br /&gt;
         '''if''' used[j] == 0&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' p[j0] != 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; алгоритм Куна суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51887</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51887"/>
				<updated>2016-01-25T22:23:14Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Анализ времени работы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Венгерский алгоритм''' (англ. '''Hungarian algorithm''') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе &amp;lt;tex&amp;gt; n^2 &amp;lt;/tex&amp;gt; ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Общая идея ===&lt;br /&gt;
Будем добавлять в рассмотрение строки матрицы одну за одной, а не рассматривать их все сразу.&lt;br /&gt;
&lt;br /&gt;
=== Описание алгоритма ===&lt;br /&gt;
* Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; \mathtt{a} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt; \mathtt{minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     заполняем массивы '''minv''' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, '''used''' {{---}} false&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m&lt;br /&gt;
         '''if''' used[j] == 0&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' p[j0] != 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; алгоритм Куна суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51886</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51886"/>
				<updated>2016-01-25T22:08:29Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Алгоритм за O(n^3) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Венгерский алгоритм''' (англ. '''Hungarian algorithm''') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Общая идея ===&lt;br /&gt;
Будем добавлять в рассмотрение строки матрицы одну за одной, а не рассматривать их все сразу.&lt;br /&gt;
&lt;br /&gt;
=== Описание алгоритма ===&lt;br /&gt;
* Добавляем в рассмотрение очередную строку матрицы &amp;lt;tex&amp;gt; \mathtt{a} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Пока нет увеличивающей цепи, начинающейся в этой строке, пересчитываем потенциал.&lt;br /&gt;
* Как только появляется увеличивающая цепь, чередуем паросочетание вдоль неё (включая тем самым последнюю строку в паросочетание), и переходим к началу (к рассмотрению следующей строки).&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt; \mathtt{minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     заполняем массивы '''minv''' {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, '''used''' {{---}} false&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m&lt;br /&gt;
         '''if''' used[j] == 0&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' p[j0] != 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы алгоритма. Во внешнем цикле мы добавляем в рассмотрение строки матрицы одну за другой. Каждая строка обрабатывается за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt;, поскольку при этом могло происходить лишь &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; пересчётов потенциала (каждый — за время &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;), для чего за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; поддерживается массив &amp;lt;tex&amp;gt; \mathtt{minv[]} &amp;lt;/tex&amp;gt;; алгоритм Куна суммарно отработает за время &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; (поскольку он представлен в форме &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; итераций, на каждой из которых посещается новый столбец).&lt;br /&gt;
&lt;br /&gt;
Итоговая асимптотика составляет &amp;lt;tex&amp;gt; O(n^3) &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;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51884</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51884"/>
				<updated>2016-01-25T20:55:18Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Венгерский алгоритм''' (англ. '''Hungarian algorithm''') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt; \mathtt{minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   &amp;lt;font color=darkgreen&amp;gt;// добавляем в рассмотрение &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ую строку матрицы &amp;lt;/font&amp;gt;&lt;br /&gt;
   '''for''' i = 1 '''to''' n&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     заполняем массивы minv {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, used {{---}} false&lt;br /&gt;
     &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец j0 &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt; // минимум в массиве minv &amp;lt;/font&amp;gt;&lt;br /&gt;
       &amp;lt;font color=darkgreen&amp;gt;// пересчитываем массив minv &amp;lt;/font&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m&lt;br /&gt;
         '''if''' used[j] == 0&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциалов u и v, соответствующее изменение массива minv&amp;lt;/font&amp;gt;&lt;br /&gt;
       '''for''' j = 0 '''to''' m&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' p[j0] != 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
     &amp;lt;font color=darkgreen&amp;gt;// ищем увеличивающую цепочку, оканчивающуюся в столбце j0, &amp;quot;раскрутить&amp;quot; которую можно, пользуясь массивом предков way&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Алгоритм Куна для поиска максимального паросочетания]]&lt;br /&gt;
* [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51877</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51877"/>
				<updated>2016-01-25T19:54:10Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Венгерский алгоритм''' (англ. '''Hungarian algorithm''') — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Вспомогательные леммы ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy) \mid x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{a[1 \dots n][1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; \mathtt{n \leqslant m} &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{u[0 \dots n], v[0 \dots n]} &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{p[0 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; \mathtt{i = 0 \dots m} &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; \mathtt{p[i]} &amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; \mathtt{p[0]} &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{minv[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt; \mathtt{minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathtt{way[1 \dots m]} &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   &amp;lt;font color=darkgreen&amp;gt;// добавляем в рассмотрение &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ую строку матрицы &amp;lt;/font&amp;gt;&lt;br /&gt;
   '''for''' i = 1 '''to''' n&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     заполняем массивы minv {{---}} &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;, used {{---}} false&lt;br /&gt;
     &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец j0 &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt; // минимум в массиве minv &amp;lt;/font&amp;gt;&lt;br /&gt;
       &amp;lt;font color=darkgreen&amp;gt;// пересчитываем массив minv &amp;lt;/font&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m&lt;br /&gt;
         '''if''' used[j] == 0&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциалов u и v, соответствующее изменение массива minv&amp;lt;/font&amp;gt;&lt;br /&gt;
       '''for''' j = 0 '''to''' m&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' p[j0] != 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
     &amp;lt;font color=darkgreen&amp;gt;// ищем увеличивающую цепочку, оканчивающуюся в столбце j0, &amp;quot;раскрутить&amp;quot; которую можно, пользуясь массивом предков way&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51870</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51870"/>
				<updated>2016-01-25T09:02:48Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Алгоритм за O(n^3) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Венгерский алгоритм — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|паросочетания]] определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Некоторые полезные утверждения ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy)|\ x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; a[1 \dots n][1 \dots m] &amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt; n \leq m &amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; u[0 \dots n], v[0 \dots n] &amp;lt;/tex&amp;gt; {{---}} массивы потенциалов. Изначально нулевые, что верно для матрицы, состоящей из 0 строк.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; p[0 \dots m] &amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt; i = 0 \dots m &amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt; p[i] &amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt; p[0] &amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; minv[1 \dots m] &amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt; minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; way[1 \dots m] &amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|увеличивающую цепочку]].&lt;br /&gt;
&lt;br /&gt;
 '''function''' hungarianAlgorithm(a):&lt;br /&gt;
   &amp;lt;font color=darkgreen&amp;gt;// добавляем в рассмотрение &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ую строку матрицы &amp;lt;/font&amp;gt;&lt;br /&gt;
   '''for''' i = 1 '''to''' n&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     '''for''' i = 0 '''to''' m + 1&lt;br /&gt;
       minv[i] = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;&lt;br /&gt;
       used[i] = false&lt;br /&gt;
     &amp;lt;font color=darkgreen&amp;gt;// ищем свободный столбец j0 &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt; // минимум в массиве minv &amp;lt;/font&amp;gt;&lt;br /&gt;
       &amp;lt;font color=darkgreen&amp;gt;// пересчитываем массив minv &amp;lt;/font&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m&lt;br /&gt;
         '''if''' used[j] == 0&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       &amp;lt;font color=darkgreen&amp;gt;// производим пересчет потенциалов u и v, соответствующее изменение массива minv&amp;lt;/font&amp;gt;&lt;br /&gt;
       '''for''' j = 0 '''to''' m&lt;br /&gt;
         '''if''' used[j]&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else'''&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt; \delta &amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' p[j0] != 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
     &amp;lt;font color=darkgreen&amp;gt;// ищем увеличивающую цепочку, оканчивающуюся в столбце j0, &amp;quot;раскрутить&amp;quot; которую можно, пользуясь массивом предков way&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' true&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; 0&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51866</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51866"/>
				<updated>2016-01-25T08:00:11Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Анализ времени работы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Венгерский алгоритм — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|паросочетания]] определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Некоторые полезные утверждения ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy)|\ x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
[[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Поиск максимального паросочетания]] или [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|минимального вершинного покрытия]] в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a[1 \dots n][1 \dots m]&amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt;n \leq m&amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;u[0 \dots n], v[0 \dots n]&amp;lt;/tex&amp;gt; {{---}} массивы потенциалов. Изначально нулевые, что верно для матрицы, состоящей из 0 строк.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;p[0 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt;i = 0 \dots m&amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt;p[0]&amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;way[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить увеличивающую цепочку.&lt;br /&gt;
&lt;br /&gt;
 '''hungarianAlgorithm'''(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n:&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     '''for''' i = 0 '''to''' m + 1:&lt;br /&gt;
       minv[i] = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       used[i] = false&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m:&lt;br /&gt;
         '''if''' used[j] == 0:&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]:&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;:&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m:&lt;br /&gt;
         '''if''' used[j]:&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;;&lt;br /&gt;
         '''else''':&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1;&lt;br /&gt;
       '''if''' p[j0] != 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51865</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51865"/>
				<updated>2016-01-25T07:21:35Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Постановка задачи */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Венгерский алгоритм — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан [[Основные определения теории графов|взвешенный полный двудольный граф]] c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|полное паросочетание минимального веса]]. Вес [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|паросочетания]] определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Некоторые полезные утверждения ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy)|\ x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
Поиск максимального паросочетания или минимального вершинного покрытия в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a[1 \dots n][1 \dots m]&amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt;n \leq m&amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;u[0 \dots n], v[0 \dots n]&amp;lt;/tex&amp;gt; {{---}} массивы потенциалов. Изначально нулевые, что верно для матрицы, состоящей из 0 строк.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;p[0 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt;i = 0 \dots m&amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt;p[0]&amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;way[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить увеличивающую цепочку.&lt;br /&gt;
&lt;br /&gt;
 '''hungarianAlgorithm'''(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n:&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     '''for''' i = 0 '''to''' m + 1:&lt;br /&gt;
       minv[i] = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       used[i] = false&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m:&lt;br /&gt;
         '''if''' used[j] == 0:&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]:&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;:&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m:&lt;br /&gt;
         '''if''' used[j]:&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;;&lt;br /&gt;
         '''else''':&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1;&lt;br /&gt;
       '''if''' p[j0] != 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51118</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51118"/>
				<updated>2016-01-14T02:33:43Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Ссылки */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Венгерский алгоритм — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан взвешенный полный двудольный граф c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем полное паросочетание минимального веса. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Некоторые полезные утверждения ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy)|\ x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
Поиск максимального паросочетания или минимального вершинного покрытия в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a[1 \dots n][1 \dots m]&amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt;n \leq m&amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;u[0 \dots n], v[0 \dots n]&amp;lt;/tex&amp;gt; {{---}} массивы потенциалов. Изначально нулевые, что верно для матрицы, состоящей из 0 строк.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;p[0 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt;i = 0 \dots m&amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt;p[0]&amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;way[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить увеличивающую цепочку.&lt;br /&gt;
&lt;br /&gt;
 '''hungarianAlgorithm'''(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n:&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     '''for''' i = 0 '''to''' m + 1:&lt;br /&gt;
       minv[i] = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       used[i] = false&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m:&lt;br /&gt;
         '''if''' used[j] == 0:&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]:&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;:&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m:&lt;br /&gt;
         '''if''' used[j]:&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;;&lt;br /&gt;
         '''else''':&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1;&lt;br /&gt;
       '''if''' p[j0] != 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
* [http://e-maxx.ru/algo/assignment_hungary Венгерский алгоритм решения задачи о назначениях]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51117</id>
		<title>Венгерский алгоритм решения задачи о назначениях</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D1%85&amp;diff=51117"/>
				<updated>2016-01-14T02:32:13Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: /* Алгоритм за O(n^3) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Венгерский алгоритм — алгоритм, решающий задачу о назначениях за полиномиальное время. Оригинальная версия была придумана и разработана Х. Куном в 1955 году и имела асимптотику &amp;lt;tex&amp;gt; O(n^4) &amp;lt;/tex&amp;gt;, но позже Эдмонс и Карп (а также, независимо от них, Томидзава) показали, что можно улучшить ее до &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан взвешенный полный двудольный граф c целыми весами ребер &amp;lt;tex&amp;gt; K_{n, n} &amp;lt;/tex&amp;gt;, нужно найти в нем полное паросочетание минимального веса. Вес паросочетания определяется как сумма весов его ребер. Далее будем обозначать левую и правую доли графа за &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно, вес ребра &amp;lt;tex&amp;gt; xy &amp;lt;/tex&amp;gt; — как &amp;lt;tex&amp;gt; c(xy) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Некоторые полезные утверждения ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить (увеличить или уменьшить) на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.&lt;br /&gt;
|proof=&lt;br /&gt;
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Указанная операция изменит на одно и то же число вес любого паросочетания. Значит, ребро, которое принадлежало оптимальному паросочетанию в старом графе, в новом графе тоже будет ему принадлежать.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.&lt;br /&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;Y&amp;lt;/tex&amp;gt; подмножества &amp;lt;tex&amp;gt;X', Y'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;d = \min \{c(xy)|\ x \in X \setminus X', y \in Y'\}&amp;lt;/tex&amp;gt;. Прибавим &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; ко всем весам ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;X'&amp;lt;/tex&amp;gt;. Затем отнимем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; от всех весов ребер, инцидентных вершинам из &amp;lt;tex&amp;gt;Y'&amp;lt;/tex&amp;gt; (далее для краткости эта операция обозначается как &amp;lt;tex&amp;gt; X' \uparrow\downarrow Y' &amp;lt;/tex&amp;gt;). Тогда:&lt;br /&gt;
# Веса всех ребер графа останутся неотрицательными.&lt;br /&gt;
# Веса ребер вида &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x \in X', y \in Y'&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;x \in X \backslash X', y \in Y \backslash Y'&amp;lt;/tex&amp;gt;, не изменятся.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; состоят из первых элементов множеств &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt; соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border = '1' bordercolor = 'black' rules = 'all' cellpadding = '5'&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;  &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; Y \backslash Y' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; A + d - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; C + d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; X \backslash X' &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; B - d &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Веса группы &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; будут сначала увеличены, а потом уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, поэтому они не изменятся, веса группы &amp;lt;tex&amp;gt; D &amp;lt;/tex&amp;gt; вообще изменяться не будут. Все веса группы &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; будут уменьшены на &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; — минимум среди этих весов, поэтому они останутся неотрицательными.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.&lt;br /&gt;
|proof=&lt;br /&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;
&lt;br /&gt;
# Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.&lt;br /&gt;
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.&lt;br /&gt;
# Ищем в текущем графе полное паросочетание из ребер нулевого веса: &lt;br /&gt;
#&lt;br /&gt;
#* Если оно найдено, то желаемый результат достигнут, алгоритм закончен.&lt;br /&gt;
#* В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах|нахождение минимального вершинного покрытия в двудольном графе]]). Пусть &amp;lt;tex&amp;gt; X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y_c &amp;lt;/tex&amp;gt; — множества вершин минимального вершинного покрытия из левой и правой долей (то есть, строк и столбцов) соответственно, тогда применим преобразование &amp;lt;tex&amp;gt; X_c \uparrow\downarrow (Y \setminus Y_c) &amp;lt;/tex&amp;gt;. Для этого преобразования &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будет минимумом по всем ребрам между &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;, то есть, ребер нулевого веса здесь нет, поэтому, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
&lt;br /&gt;
Поиск максимального паросочетания или минимального вершинного покрытия в двудольном графе совершается за &amp;lt;tex&amp;gt; O(n^3) &amp;lt;/tex&amp;gt; операций. При каждом повторении шагов 1-4 в матрице весов появляется новый нуль. Этот нуль соответствует некоторому новому ребру между вершинами из множеств &amp;lt;tex&amp;gt; X \setminus X_c &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; Y \setminus Y_c &amp;lt;/tex&amp;gt;. Всего в графе n^2 ребер, значит, всего будет совершено не более &amp;lt;tex&amp;gt; O(n^2) &amp;lt;/tex&amp;gt; итераций внешнего цикла. Поэтому, верхняя оценка времени работы данного метода — &amp;lt;tex&amp;gt; O(n^5) &amp;lt;/tex&amp;gt;. Более точная оценка довольно сложна и зависит от порядка чисел в матрице весов графа.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a[1 \dots n][1 \dots m]&amp;lt;/tex&amp;gt; {{---}} прямоугольная входная матрица, где &amp;lt;tex&amp;gt;n \leq m&amp;lt;/tex&amp;gt;. Матрица хранится в 1-индексации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;u[0 \dots n], v[0 \dots n]&amp;lt;/tex&amp;gt; {{---}} массивы потенциалов. Изначально нулевые, что верно для матрицы, состоящей из 0 строк.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;p[0 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив паросочетания. Для каждого стобца &amp;lt;tex&amp;gt;i = 0 \dots m&amp;lt;/tex&amp;gt; он хранит номер соответствующей выбранной строки &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt; (или 0, если ничего не выбрано). Полагаем, что &amp;lt;tex&amp;gt;p[0]&amp;lt;/tex&amp;gt; равно номеру рассматриваемой строки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, хранящий для каждого столбца j вспомогательные минимумы, необходимые для быстрого пересчета потенциала.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;minv[j] = \min_{i \in Z_1}\{a[i][j] - u[i] - v[j]\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;way[1 \dots m]&amp;lt;/tex&amp;gt; {{---}} массив, содержащий информацию о том, где эти минимумы достигаются, чтобы мы могли впоследствии восстановить увеличивающую цепочку.&lt;br /&gt;
&lt;br /&gt;
 '''hungarianAlgorithm'''(a):&lt;br /&gt;
   '''for''' i = 1 '''to''' n:&lt;br /&gt;
     p[0] = i&lt;br /&gt;
     j0 = 0&lt;br /&gt;
     '''for''' i = 0 '''to''' m + 1:&lt;br /&gt;
       minv[i] = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       used[i] = false&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       used[j0] = true&lt;br /&gt;
       i0 = p[j0]&lt;br /&gt;
       &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''for''' j = 1 '''to''' m:&lt;br /&gt;
         '''if''' used[j] == 0:&lt;br /&gt;
           cur = a[i0][j] - u[i0] - v[j]&lt;br /&gt;
           '''if''' cur &amp;lt; minv[j]:&lt;br /&gt;
             minv[j] = cur&lt;br /&gt;
             way[j] = j0&lt;br /&gt;
           '''if''' minv[j] &amp;lt; &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;:&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; = minv[j]&lt;br /&gt;
             j1 = j&lt;br /&gt;
       '''for''' j = 0 '''to''' m:&lt;br /&gt;
         '''if''' used[j]:&lt;br /&gt;
           u[p[j]] += &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
           v[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;;&lt;br /&gt;
         '''else''':&lt;br /&gt;
           minv[j] -= &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;&lt;br /&gt;
       j0 = j1;&lt;br /&gt;
       '''if''' p[j0] != 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
     '''while''' true:&lt;br /&gt;
       j1 = way[j0]&lt;br /&gt;
       p[j0] = p[j1]&lt;br /&gt;
       j0 = j1&lt;br /&gt;
       '''if''' j0 &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; 0:&lt;br /&gt;
         '''break'''&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм Венгерский алготитм в Википедии]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]&lt;br /&gt;
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&amp;amp;table=2&amp;amp;up=0 Реализация венгерского алгоритма на C++]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<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_LZMA&amp;diff=42586</id>
		<title>Алгоритм LZMA</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_LZMA&amp;diff=42586"/>
				<updated>2014-12-20T01:13:45Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;LZMA (англ. Lempel-Ziv-Markov chain-Algorithm) — алгоритм сжатия данных без потерь. Он разрабатывался с 1996-1998 гг и впервые был использован в формате 7z архиватора 7-Zip. Алгоритм использует схему сжатия данных по словарю, сходную с алгоритмом LZ77, опубликованным Авраамом Лемпелем (Abraham Lempel) и Якобом Зивом (Jacob Ziv) в 1977 году, и отличается высокой степенью сжатия, произвольным размером словаря, тогда как скорость распаковки сходна с другими алгоритмами сжатия.&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
LZMA использует алгоритм сжатия данных по словарю, чей результат закодирован интервальным кодированием, используя сложную модель вычисления вероятности появления каждого бита. Система сжатия ищет совпадения, используя словарь структур данных, и создает поток символов и ссылок на фразы, который закодирован 1 битом интервальным кодировщиком, в то же время динамическое программирование используется, чтобы выбрать оптимальный код под некоторой аппроксимацией.&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	<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_LZMA&amp;diff=41873</id>
		<title>Алгоритм LZMA</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_LZMA&amp;diff=41873"/>
				<updated>2014-12-05T19:42:35Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s111: Новая страница: «LZMA (англ. Lempel-Ziv-Markov chain-Algorithm) — алгоритм сжатия данных без потерь, разрабатываемый с 2001 го...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;LZMA (англ. Lempel-Ziv-Markov chain-Algorithm) — алгоритм сжатия данных без потерь, разрабатываемый с 2001 года.&lt;br /&gt;
&lt;br /&gt;
Алгоритм основан на схеме сжатия данных по словарю, сходной с использованной в LZ77, и обеспечивает высокий коэффициент сжатия, а также позволяет использовать словари различного размера.&lt;/div&gt;</summary>
		<author><name>Da1s111</name></author>	</entry>

	</feed>