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

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66459</id>
		<title>Алгоритмы взаимного исключения</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=66459"/>
				<updated>2018-10-07T18:31:44Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: fix typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Определения==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Взаимное исключение''' (англ. ''mutual exclusion'') — свойство построения параллельных программ, которое используется в целях предотвращения состояния гонки (англ. ''race condition''); Оно требует, чтобы один поток исполнения никогда не входил в критическую секцию одновременно с тем, как другой параллельный поток выполнения вошел в свою критическую секцию.&lt;br /&gt;
}}&lt;br /&gt;
То есть критические секции не могут выполняться параллельно: &amp;lt;tex&amp;gt;\forall i,j:i \neq j \Rightarrow CS_i \rightarrow CS_j \vee CS_j \rightarrow CS_i &amp;lt;/tex&amp;gt;. Это значит, что выполнение критических секций будет линеаризуемо. Это требование корректности протокола взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Критическая секция''' (англ. ''critical section'') — участок исполняемого кода программы, в котором производится доступ к общему ресурсу (данным или устройству), который не должен быть одновременно использован более чем одним потоком исполнения.&lt;br /&gt;
}}&lt;br /&gt;
==Проблема==&lt;br /&gt;
Проблема, с которой связаны взаимные исключения, является проблемой совместного использования ресурсов: как можно управлять доступом нескольких процессов к общему ресурсу, когда каждый процесс нуждается в исключительном контроле над этим ресурсом при выполнении своей работы? Решение — делать доступным общий ресурс только тогда, когда процесс находится в определенном сегменте кода, называемом критической секцией. И контролировать доступ к общему ресурсу, контролируя каждое взаимное выполнение той части программы, в которой будет использоваться ресурс.&lt;br /&gt;
&lt;br /&gt;
Успешное решение этой проблемы должно иметь по крайней мере три свойства:&lt;br /&gt;
&lt;br /&gt;
Условие корректности:&lt;br /&gt;
#'''Взаимное исключение''' (англ. ''mutual exclusion''): только один поток может быть в критической секции.&lt;br /&gt;
Условия прогресса:&lt;br /&gt;
#'''Отсутствие взаимоблокировок''' (англ. ''deadlocks''): если несколько потоков пытаются войти в критическую секцию, то хотя бы один из них должен войти в критическую секцию за конечное время.&lt;br /&gt;
#'''Отсутствие голодания''' (англ. ''starvation-freedom''): если какой-то поток пытается войти в критическую секцию, то он войдет в критическую секцию за конечное время. Может быть последовательно усиленно, превращаясь в условие честности (англ. ''fairness'').&lt;br /&gt;
#*Квадратичное ожидание (англ. ''quadratic wait'') — &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Линейное ожидание (англ. ''linear wait'') — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций.&lt;br /&gt;
#*Первый пришел, первый обслужен (англ. ''first come first served'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Требование &amp;lt;tex&amp;gt;First Come First Served (FCFS)&amp;lt;/tex&amp;gt; формализуется так:&lt;br /&gt;
#Метод &amp;lt;tex&amp;gt;lock&amp;lt;/tex&amp;gt; должен состоять из двух последовательных секций.&lt;br /&gt;
   '''def''' lock():&lt;br /&gt;
      '''doorway'''&lt;br /&gt;
      '''waiting'''&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; должны быть &amp;lt;tex&amp;gt;wait free&amp;lt;/tex&amp;gt;, то есть выполняться за конечное число шагов, независимо от других потоков.&lt;br /&gt;
#Секция &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; должна выполнять условие: Если &amp;lt;tex&amp;gt;DW_i \Rightarrow DW_j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;res(WT_i) \Rightarrow res(WT_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Каждая программа может быть разделена на четыре секции, что приводит к четырем состояниям. [[Файл: State_graph2.png|thumb|right|Порядок перехода между состояниями]]&lt;br /&gt;
;Non-Critical Section: Операция находится вне критической секции; этот процесс не использует или не запрашивает общий ресурс.&lt;br /&gt;
;Trying: Процесс пытается войти в критический раздел.&lt;br /&gt;
;Critical Section: В этом разделе разрешен доступ к общему ресурсу.&lt;br /&gt;
;Exit :Процесс выходит из критического раздела и делает доступный общий ресурс другим процессам. &lt;br /&gt;
&lt;br /&gt;
Если процесс хочет войти в критический раздел, он должен сначала выполнить раздел &amp;lt;tex&amp;gt;try&amp;lt;/tex&amp;gt; и подождать, пока он не получит доступ к критическому разделу. После того, как процесс выполнил свой критический раздел и завершился с общими ресурсами, ему необходимо выполнить раздел выхода, чтобы освободить их для использования другими процессами. Затем процесс возвращается в некритический раздел.&lt;br /&gt;
&lt;br /&gt;
==Алгоритмы взаимного исключения==&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Простейший алгоритм параллельного программирования для взаимного исключения потоков исполнения кода, разработанный Гарри Петерсоном в &amp;lt;tex&amp;gt;1981&amp;lt;/tex&amp;gt; г.&amp;lt;ref name=&amp;quot;original&amp;quot;&amp;gt;G. L. Peterson: &amp;quot;Myths About the Mutual Exclusion Problem&amp;quot;, ''Information Processing Letters'' 12(3) 1981, 115–116&amp;lt;/ref&amp;gt; While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.&amp;lt;/ref&amp;gt; Хотя изначально был сформулирован для 2-поточного случая, алгоритм может быть обобщён для произвольного количества потоков. Гарантирует взаимное исключение, отсутствие взаимной блокировки и отсутствие голодания.&lt;br /&gt;
&lt;br /&gt;
Принцип работы: перед тем как начать исполнение критической секции кода, поток должен вызвать процедуру &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; со своим номером в качестве параметра. Она должна организовать ожидание потоком своей очереди входа в критическую секцию. После исполнения критической секции и выхода из неё поток вызывает другую процедуру &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt;, после чего уже другие потоки смогут войти в критическую область. Рассмотрим реализацию этого принципа алгоритмом Петерсона для двух потоков.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 or 1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' want[2]&lt;br /&gt;
   '''shared int''' victim&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
        want[id] = true&lt;br /&gt;
        victim = id&lt;br /&gt;
        '''while''' want[1-id] '''and'''&lt;br /&gt;
              victim == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
===Корректность алгоритма===&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Потоки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; никогда не могут попасть в критическую секцию в один момент времени: если &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; вошёл в секцию, он установил &amp;lt;tex&amp;gt;want[0]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;true&amp;lt;/tex&amp;gt;. Тогда либо &amp;lt;tex&amp;gt;want[1] = false&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; не в критической секции), либо &amp;lt;tex&amp;gt;waiting = 1&amp;lt;/tex&amp;gt; (тогда поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию и крутится в цикле), либо поток &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; пытается войти в критическую секцию после установки &amp;lt;tex&amp;gt;want[1] = true&amp;lt;/tex&amp;gt;, но до установки &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt; и цикла. Таким образом, если оба процесса находятся в критической секции, должно быть &amp;lt;tex&amp;gt; want[0] \space and \space want[1] \space and \space waiting = 0 \space and \space waiting = 1 &amp;lt;/tex&amp;gt;, но такого не может быть одновременно и мы пришли к противоречию.&lt;br /&gt;
&lt;br /&gt;
=====Отсутствие взаимной блокировки=====&lt;br /&gt;
Для того, чтобы оба процесса находились в ожидании, необходимы противоположные значения переменной &amp;lt;tex&amp;gt;waiting&amp;lt;/tex&amp;gt;, что невозможно.&lt;br /&gt;
=====Отсутствие голодания=====&lt;br /&gt;
Возможна ситуация, когда один процесс будет несколько раз подряд захватывать себе критическую секцию, а другой, изъявивший желание попасть туда, будет ждать. В алгоритме Петерсона процесс не будет ждать дольше, чем один вход в критическую секцию: после выполнения &amp;lt;tex&amp;gt;unlock()&amp;lt;/tex&amp;gt; и повторного захода в &amp;lt;tex&amp;gt;lock()&amp;lt;/tex&amp;gt; процесс установит себя как ждущего и попадёт в цикл, который не завершится, пока не отработает другой процесс.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков===&lt;br /&gt;
Обобщение Алгоритм Петерсона для &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; потоков.  Гарантирует взаимное исключение, отсутствие блокировки и отсутствие голодания. Но алгоритм не очень честный. &amp;quot;Невезучий&amp;quot; поток может ждать пока другие потоки &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt; раз войдут в критическую секцию (квадратичное ожидание).&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared int''' level[N]&lt;br /&gt;
   '''shared int''' victim[N]&lt;br /&gt;
   '''def''' lock: &lt;br /&gt;
     '''for''' j = 1..N-1:  &amp;lt;font color=green&amp;gt;//Для входа в CS надо пройти на N-1 уровней&amp;lt;/font&amp;gt;&lt;br /&gt;
        level[id] = j  &amp;lt;font color=green&amp;gt;//Обобщаем want на уровень j: level[id] &amp;gt;= j&amp;lt;/font&amp;gt;&lt;br /&gt;
        victim[j] = id  &amp;lt;font color=green&amp;gt;//Своя жертва на каждом уровне&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''while''' '''exist''' k: k != id '''and'''  &amp;lt;font color=green&amp;gt;//Для прохода на следующий уровень соревнуемся со всеми другими потоками&amp;lt;/font&amp;gt;&lt;br /&gt;
              level[k] &amp;gt;= j '''and'''&lt;br /&gt;
              victim[j] == id:&lt;br /&gt;
           '''pass'''&lt;br /&gt;
   &lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     level[id] = 0&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Алгоритм Лампорта – алгоритм разделения общих ресурсов между несколькими потоками обладающий взаимным исключением. Опубликован Лесли Лампортом в 1974 году. &amp;lt;ref&amp;gt;[http://lamport.azurewebsites.net/pubs/bakery.pdf? A New Solution of Dijkstra's Concurrent Programming Problem]&amp;lt;/ref&amp;gt; Гарантирует взаимное&lt;br /&gt;
исключение, отсутствие блокировки и линейное ожидание.&lt;br /&gt;
=====Аналогия=====&lt;br /&gt;
Алгоритм реализует идею пекарни с устройством, выдающим номерки у входа. Каждому входящему покупателю выдаётся номерок на единицу больше предыдущего. Общий счётчик показывает номер обслуживаемого в данный момент клиента. Все остальные покупатели ждут, пока не закончат обслуживать текущего клиента и табло покажет следующий номер. После того как клиент сделает покупку и сдаст свой номерок, служащий увеличивает на единицу допустимые для выдачи устройством у входа номера. Если совершивший покупку клиент захочет снова что-нибудь купить, он должен будет снова взять номерок у входа и встать в общую очередь.&lt;br /&gt;
&lt;br /&gt;
Пусть покупатели это потоки, получившие номера &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=====Критическая секция=====&lt;br /&gt;
Когда поток хочет войти в критическую секцию, он должен проверить номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, полученные другими потоками, и убедиться, что у него меньший номер. В случае совпадения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; у двух или нескольких потоков, в критическую секцию входит поток с наименьшим номером потока &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt;) &amp;lt; (n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;, i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;),&lt;br /&gt;
что эквивалентно:&lt;br /&gt;
 (n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) or ((n&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; == n&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;) and (i&amp;lt;sub&amp;gt;a&amp;lt;/sub&amp;gt; &amp;lt; i&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt;))&lt;br /&gt;
Когда поток заканчивает работу в критической секции, он освобождает номер ''n'' и выходит из критической секции.&lt;br /&gt;
&lt;br /&gt;
=====Псевдокод=====&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label) + 1&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           want[k] '''and'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     want[id] = false&lt;br /&gt;
&lt;br /&gt;
Обладает свойством первый пришел, первый обслужен (&amp;lt;tex&amp;gt;FCFS&amp;lt;/tex&amp;gt;), за счет того, что поток &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; выполнивший &amp;lt;tex&amp;gt;doorway (DW)&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, имеет более ранний номер в очереди. Но метки должны быть бесконечными (их можно заменить на конечные метки).&lt;br /&gt;
&lt;br /&gt;
=====Взаимное исключение=====&lt;br /&gt;
Допустим, что два потока одновременно в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Значит поток &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; зашел в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; последним, в то время как другой поток &amp;lt;tex&amp;gt;k != id&amp;lt;/tex&amp;gt; уже был в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt;. Но зайти в &amp;lt;tex&amp;gt;CS&amp;lt;/tex&amp;gt; можно если &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;(label[k], k) &amp;gt; (label[id], id)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1:''' &amp;lt;tex&amp;gt;want[k] == false&amp;lt;/tex&amp;gt; &lt;br /&gt;
*Противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2:''' &amp;lt;tex&amp;gt;(label[k], k) &amp;gt;= (label[id], id)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Но значит другой поток зашел по &amp;lt;tex&amp;gt;want[id] == false&amp;lt;/tex&amp;gt; выполнив свой &amp;lt;tex&amp;gt;doorway&amp;lt;/tex&amp;gt; до потока &amp;lt;tex&amp;gt;id&amp;lt;/tex&amp;gt; - противоречие.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Лампорта (вариант &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;)===&lt;br /&gt;
Еще одна реализация алгоритма Лампорта. Метки тоже могут быть бесконечными, несмотря на то, что мы их и сбрасываем при выходе из критической секции.&lt;br /&gt;
&lt;br /&gt;
   '''threadlocal int''' id  &amp;lt;font color=green&amp;gt;// 0 to N-1&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''shared boolean''' want[N] '''init''' false&lt;br /&gt;
   '''shared int''' label[N] '''init''' 0&lt;br /&gt;
   '''def''' lock:&lt;br /&gt;
     want[id] = true&lt;br /&gt;
     label[id] = '''max'''(label!='''inf''') + 1&lt;br /&gt;
     want[id] = false&lt;br /&gt;
     '''while''' '''exists''' k: k != id '''and'''&lt;br /&gt;
           (want[k] '''or'''&lt;br /&gt;
           (label[k], k) &amp;lt; (label[id], id)) :&lt;br /&gt;
        '''pass'''&lt;br /&gt;
   '''def''' unlock:&lt;br /&gt;
     label[id] = '''inf'''&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Стек_Трайбера]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [https://en.wikipedia.org/wiki/Mutual_exclusion Mutual exclusion]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm Lamports bakery algorithm]&lt;br /&gt;
* [http://lamport.azurewebsites.net/pubs/bakery.pdf Original lamports bakery algorithm]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Peterson%27s_algorithm Petersons algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Параллельное программирование]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%B0_%D0%A2%D1%8C%D1%8E%D1%80%D0%B8%D0%BD%D0%B3%D0%B0&amp;diff=66170</id>
		<title>Машина Тьюринга</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%B0_%D0%A2%D1%8C%D1%8E%D1%80%D0%B8%D0%BD%D0%B3%D0%B0&amp;diff=66170"/>
				<updated>2018-06-25T07:07:04Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Многоленточная машина Тьюринга */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
'''Машина Тьюринга''' (англ. ''Turing machine'') — модель абстрактного вычислителя, предложенная британским математиком Аланом Тьюрингом в 1936 году. Эта модель позволила Тьюрингу доказать два утверждения. Первое — проблема останова неразрешима, т.е. не существует такой машины Тьюринга, которая способна определить, что другая произвольная машина Тьюринга на её ленте зациклится или прекратит работу. Второе — не существует такой машины Тьюринга, которая способна определить, что другая произвольная машина Тьюринга на её ленте когда-нибудь напечатает заданный символ. В этом же году был высказан тезис Чёрча-Тьюринга, который терминах теории рекурсии формулируется как точное описание интуитивного понятия вычислимости классом общерекурсивных функций. В этой формулировке часто упоминается как просто тезис Чёрча. В терминах вычислимости по Тьюрингу тезис гласит, что для любой алгоритмически вычислимой функции существует вычисляющая её значения машина Тьюринга. В виду того, что классы частично вычислимых по Тьюрингу и частично рекурсивных функций совпадают, утверждение объединяют в единый тезис Чёрча — Тьюринга.&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;
|definition=&lt;br /&gt;
Формально '''машина Тьюринга''' (англ. ''Turing machine'') определяется как кортеж из восьми элементов &amp;lt;tex&amp;gt;\langle \Sigma, \Pi, B, Q, Y, N, S, \delta \rangle&amp;lt;/tex&amp;gt;, где&lt;br /&gt;
* &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt; — алфавит, из букв которого могут состоять входные слова,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\Pi \supset \Sigma&amp;lt;/tex&amp;gt; — символы, которые могут быть записаны на ленту в процессе работы машины,&lt;br /&gt;
* &amp;lt;tex&amp;gt;B \in \Pi \setminus \Sigma&amp;lt;/tex&amp;gt; ­— пробельный символ (от слова ''blank''),&lt;br /&gt;
* &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; — множество состояний управляющего автомата,&lt;br /&gt;
* &amp;lt;tex&amp;gt;Y \in Q&amp;lt;/tex&amp;gt; — допускающее состояние автомата,&lt;br /&gt;
* &amp;lt;tex&amp;gt;N \in Q&amp;lt;/tex&amp;gt; — отвергающее состояние автомата,&lt;br /&gt;
* &amp;lt;tex&amp;gt;S \in Q&amp;lt;/tex&amp;gt; — стартовое состояние автомата,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\delta : Q \times \Pi \to Q \times \Pi \times \{ \leftarrow, \rightarrow, \downarrow \}&amp;lt;/tex&amp;gt; — всюду определённая функция перехода автомата.&lt;br /&gt;
}}&lt;br /&gt;
Отметим, что существуют различные вариации данного выше определения (например, без отвергающего состояния или с множеством допускающих состояний), которые не влияют на вычислительные способности машины Тьюринга.&lt;br /&gt;
&lt;br /&gt;
=== Определение процесса работы ===&lt;br /&gt;
Кроме формального определения самой машины требуется также формально описать процесс её работы. В определении для простоты будем предполагать, что головка в процессе работы не записывает на ленту символ &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. Это не ограничивает вычислительной мощности машин Тьюринга, поскольку для каждой машины можно сопоставить аналогичную ей, но не пищущую &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; на ленту.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=conf&lt;br /&gt;
|definition=&lt;br /&gt;
Назовём '''конфигурацией''' машины Тьюринга тройку &amp;lt;tex&amp;gt;\langle w, q, v \rangle&amp;lt;/tex&amp;gt;, где&lt;br /&gt;
* &amp;lt;tex&amp;gt;q \in Q&amp;lt;/tex&amp;gt; — текущее состояние автомата,&lt;br /&gt;
* &amp;lt;tex&amp;gt;w, v \in (\Pi \setminus \{B\})^*&amp;lt;/tex&amp;gt; — строки слева и справа от головки до первого пробельного символа соответственно.&lt;br /&gt;
}}&lt;br /&gt;
В данной записи головка находится над ячейкой, на которой написана первая буква &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; (или &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;v = \varepsilon&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
В дальнейшем используются следующие обозначения: &amp;lt;tex&amp;gt;x, y, z \in \Pi&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;w, v \in \Pi^*&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Определим на конфигурациях отношение перехода &amp;lt;tex&amp;gt;\langle w_1, q_1, v_1 \rangle \vdash \langle w_2, q_2, v_2 \rangle&amp;lt;/tex&amp;gt;:&lt;br /&gt;
* если &amp;lt;tex&amp;gt;\delta(q, x) = \langle p, y, \leftarrow \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\langle wz, q, xv \rangle \vdash \langle w, p, zyv \rangle&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* если &amp;lt;tex&amp;gt;\delta(q, x) = \langle p, y, \rightarrow \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\langle w, q, xv \rangle \vdash \langle wy, p, v \rangle&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* если &amp;lt;tex&amp;gt;\delta(q, x) = \langle p, y, \downarrow \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\langle w, q, xv \rangle \vdash \langle w, p, yv \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Особо следует рассмотреть случай переходов по пробельному символу:&lt;br /&gt;
* если &amp;lt;tex&amp;gt;\delta(q, B) = \langle p, y, \leftarrow \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\langle wz, q, \varepsilon \rangle \vdash \langle w, p, zy \rangle&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* если &amp;lt;tex&amp;gt;\delta(q, B) = \langle p, y, \rightarrow \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\langle w, q, \varepsilon \rangle \vdash \langle wy, p, \varepsilon \rangle&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* если &amp;lt;tex&amp;gt;\delta(q, B) = \langle p, y, \downarrow \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\langle w, q, \varepsilon \rangle \vdash \langle w, p, y \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Очевидно, что определённое отношение является функциональным: для каждой конфигурации &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; существует не более одной конфигурации &amp;lt;tex&amp;gt;C'&amp;lt;/tex&amp;gt;, для которой &amp;lt;tex&amp;gt;C \vdash C'&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для машины Тьюринга, которая пишет символ &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; на ленту также можно дать аналогичное формальное определение. Оно будет отличаться тем, что символы в строчках конфигурации могут содержать пробелы, и для того, чтобы эти строчки имекли конечную длину, нужно аккуратно учесть наличие пробелов при записи правил перехода.&lt;br /&gt;
&lt;br /&gt;
=== Результат работы ===&lt;br /&gt;
Машину Тьюринга можно рассматривать как распознаватель слов [[Основные определения: алфавит, слово, язык, конкатенация, свободный моноид слов; операции над языками|формального языка]]. Пусть &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — машина Тьюринга, распознаваемый ей язык определяется как &amp;lt;tex&amp;gt;\mathcal L(M) = \{ x \in \Sigma^* \mid \exists y, z \in \Pi^*: \langle \varepsilon, S, x \rangle \vdash^* \langle y, Y, z \rangle \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Также можно рассматривать машины Тьюринга как преобразователь входных данных в выходные. Машина &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; задаёт [[Вычислимые функции|вычислимую функцию]] &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, причём &amp;lt;tex&amp;gt;f(x) = y \Leftrightarrow \exists z \in \Pi^* : \langle \varepsilon, S, x \rangle \vdash^* \langle z, Y, y \rangle&amp;lt;/tex&amp;gt;. Переход автомата в состояние &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; можно интерпретировать как аварийное завершение программы (например, при некорретном входе).&lt;br /&gt;
&lt;br /&gt;
Примеры машин-распознавателей и машин-преобразователей будут даны ниже.&lt;br /&gt;
&lt;br /&gt;
== Примеры машин Тьюринга ==&lt;br /&gt;
=== Прибавление единицы ===&lt;br /&gt;
Для начала приведём пример машины-преобразователя, которая прибавляет единицу к числу, записанному на ленте в двоичной записи от младшего бита к старшему. Алгоритм следующий:&lt;br /&gt;
* в стартовом состоянии головка идёт вправо от младшего бита к старшему, заменяя все единицы на нули,&lt;br /&gt;
* встретив нуль или пробельный символ головка записывает единицу, после чего переходит в состояние &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* в состоянии &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt; головка идёт влево от старшего бита к младшему, не изменяя символы 0 и 1 на ленте,&lt;br /&gt;
* встретив в состоянии &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt; пробельный символ, головка перемещается на один символ вправо и переходит в состояние &amp;lt;tex&amp;gt;Y&amp;lt;/tex&amp;gt;, завершая работу.&lt;br /&gt;
&lt;br /&gt;
Формально: &amp;lt;tex&amp;gt;\Sigma = \{0, 1 \}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\Pi = \{0, 1, B\}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;Q = \{S, R, Y, N \}&amp;lt;/tex&amp;gt;. Таблица функции &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; приведена ниже:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot; cellspacing=&amp;quot;5&amp;quot;&lt;br /&gt;
 |-&lt;br /&gt;
 |width=&amp;quot;30&amp;quot;|&lt;br /&gt;
 |width=&amp;quot;100&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |width=&amp;quot;100&amp;quot;| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |width=&amp;quot;100&amp;quot;| &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, 1, \downarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle S, 0, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, B, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, 0, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, 1, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle Y, B, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Проверка того, является ли слово палиндромом ===&lt;br /&gt;
В качестве примера машины-распознавателя приведём машину, распознающую палиндромы над алфавитом &amp;lt;tex&amp;gt;\{0, 1\}&amp;lt;/tex&amp;gt;. Алгоритм следующий:&lt;br /&gt;
* если строка на ленте — пустая, то перейти в допускающее состояние&lt;br /&gt;
* надо запомнить первый символ слова в состоянии автомата,&lt;br /&gt;
* стереть его,&lt;br /&gt;
* перейти в конец ленты:&lt;br /&gt;
** если оставшаяся строка на ленте — пустая, то перейти в допускающее состояние&lt;br /&gt;
** если последний символ совпадает с запомненным, стереть его, перейти в начало ленты и повторить с первого шага&lt;br /&gt;
** в случае несовпадения перейти в отвергающее состояние&lt;br /&gt;
&lt;br /&gt;
Формально: &amp;lt;tex&amp;gt;\Sigma = \{0, 1\}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\Pi = \{0, 1, B\}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;Q = \{S, F_0, F_1, B_0, B_1, R \}&amp;lt;/tex&amp;gt;. Таблица функции &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt; приведена ниже:&lt;br /&gt;
{| border=&amp;quot;0&amp;quot; cellspacing=&amp;quot;5&amp;quot;&lt;br /&gt;
 |-&lt;br /&gt;
 |width=&amp;quot;30&amp;quot;|&lt;br /&gt;
 |width=&amp;quot;100&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |width=&amp;quot;100&amp;quot;| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |width=&amp;quot;100&amp;quot;| &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle F_0, B, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle F_1, B, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle Y, B, \downarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle F_0, 0, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle F_0, 1, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle B_0, B, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;F_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle F_1, 0, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle F_1, 1, \rightarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle B_1, B, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;B_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, B, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle N, 1, \downarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle Y, B, \downarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;B_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle N, 0, \downarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, B, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle Y, B, \downarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 | &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, 0, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle R, 1, \leftarrow \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 | &amp;lt;tex&amp;gt;\langle S, B, \rightarrow \rangle&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;
Машиной Тьюринга с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; дорожками называется вычислитель, аналогичный машине Тьюринга, лишь с тем отличием, что лента состоит из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; дорожек, на каждой из которых записаны символы ленточного алфавита. У многодорожечной машины одна головка, которая за один шаг переходит в одном направлении на всех дорожках одновременно. Соответственно, функция перехода имеет тип &amp;lt;tex&amp;gt;\delta : Q \times \Pi^n \to Q \times \Pi^n \times \{\leftarrow, \rightarrow, \downarrow\}&amp;lt;/tex&amp;gt;. Многодорожечная машина Тьюринга тривиально эквивалентна обычной с ленточным алфавитом &amp;lt;tex&amp;gt;\Pi' = \Pi^n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Машина Тьюринга с полубесконечной лентой ===&lt;br /&gt;
Заменив у машины Тьюринга бесконечную в обе стороны ленту на бесконечную в одну сторону, мы не теряем в вычислительной мощности. По произвольной машине Тьюринга строится двухдорожечная машина с полубесконечной лентой.&lt;br /&gt;
{{Теорема&lt;br /&gt;
|author=&lt;br /&gt;
|statement=Для любой машины Тьюринга существует эквивалентная машина Тьюринга, работающая на полубесконечной ленте.&lt;br /&gt;
|proof=Существует алгоритм, по которому для любой машины Тьюринга может быть построена эквивалентная машина Тьюринга с объявленным свойством. Сначала занумеруем ячейки рабочей ленты машины Тьюринга с ''бесконечной лентой'' следующим образом:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Mt1.png]]&lt;br /&gt;
&lt;br /&gt;
Затем перенумеруем ячейки, и запишем символ &amp;lt;tex&amp;gt;c \in \Pi \setminus \Sigma, B&amp;lt;/tex&amp;gt; в начало ленты, который будет означать границу рабочей зоны:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Mt2.png]]&lt;br /&gt;
&lt;br /&gt;
Наконец, изменим машину Тьюринга, удвоив число её состояний, и изменим сдвиг головки так, чтобы в одной группе состояний работа машины была бы эквивалентна её работе в заштрихованной зоне, а в другой группе состояний машина работала бы так, как исходная машина работает в незаштрихованной зоне. Если при работе машины Тьюринга встретится символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, значит головка достигла границы рабочей зоны:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Mt3.png]]&lt;br /&gt;
&lt;br /&gt;
Начальное состояние новой машины Тьюринга устанавливается в одной или другой зоне в зависимости от того, в какой части исходной ленты располагалась головка считывания-записи в исходной конфигурации.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Многоленточная машина Тьюринга ===&lt;br /&gt;
В отличие от многодорожечной машины Тьюринга, ленты не зависят друг от друга и головки во время одного шага могут перемещаться по-разному. То есть, функция перехода теперь имеет тип &amp;lt;tex&amp;gt;\delta : Q \times \Pi^n \to Q \times \Pi^n \times \{\leftarrow, \rightarrow, \downarrow\}^n&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Многоленточная машина с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; дорожками эмулируется многодорожечной машиной с &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt; дорожками следующим образом: каждая нечётная дорожка соответствует ленте исходной машины, а на каждой чётной дорожке отмечены специальным символом &amp;lt;tex&amp;gt;*&amp;lt;/tex&amp;gt; позиция головки на ленте выше (считаем, что ленты нумеруются сверху вниз).&lt;br /&gt;
&lt;br /&gt;
Каждый шаг исходной машины эмулируется конечной последовательностью шагов построенной машины следующим образом: исходно головка находится в позиции самой левой отметки и идёт вправо до самой правой отметки, запоминая прочитанные около символов &amp;lt;tex&amp;gt;*&amp;lt;/tex&amp;gt; символы в состоянии. Пройдя до самой правой отметки, головка возвращается влево, совершая необходимые действия (переписывая символы около отметок и передвигая сами отметки). После такого прохода головка переходит в следующее состояние, завершая эмуляцию шага.&lt;br /&gt;
&lt;br /&gt;
Аланом Тьюрингом было сформулировано следующее утверждение:&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|about=Тезис Чёрча-Тьюринга&lt;br /&gt;
|statement=&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;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.cs.virginia.edu/~robins/Turing_Paper_1936.pdf Alan Turing {{---}} On computable numbers, with an application to the Entscheidungsproblem.]&lt;br /&gt;
* [http://www.ccs.neu.edu/home/viola/classes/papers/HennieStearns66.pdf F. C. Hennie, R. E. Stearn {{---}} Two-tape simulation of multitape Turing machines.]&lt;br /&gt;
* [http://www.cs.princeton.edu/theory/index.php/Compbook/Draft Sanjeev Arora, Boaz Barak {{---}} Computational Complexity: A Modern Approach.]&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.145.8958 Turlough Neary, Damien Woods {{---}} Four Small Universal Turing Machines.]&lt;br /&gt;
* [http://www.jflap.org/ JFLAP {{---}} ПО для изучения формальных языков, включает в себя эмулятор одноленточных и многоленточных машин Тьюринга с визуальным редактором.]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Теория вычислимости]]&lt;br /&gt;
[[Категория: Вычислительные формализмы]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Link-Cut_Tree&amp;diff=65473</id>
		<title>Link-Cut Tree</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Link-Cut_Tree&amp;diff=65473"/>
				<updated>2018-05-12T22:03:10Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* cut(v) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Динамические деревья''' (англ.''dynamic tree'') используются в двух областях: [[Определение сети, потока|потоки]] и динамические графы.&lt;br /&gt;
В первом случае динамические деревья позволяют построить эффективные алгоритмы для задачи о поиске максимального потока.&lt;br /&gt;
В динамическом графе периодически происходят изменения: появляются и исчезают ребра, меняются их веса. Нужно быстро обрабатывать изменения, а также уметь [[Отношение связности, компоненты связности | проверять связность]], [[Алгоритмы на деревьях|искать диаметр]]. Динамические деревья являются инструментом, который позволяет легко решать эти задачи.  Динамические деревья особенно эффективны, когда нужно работать с большими деревьями и большим количеством запросов '''link''' и '''cut'''.&lt;br /&gt;
&lt;br /&gt;
'''Link-cut tree'''  {{---}} это структура данных, которая хранит [[Дерево, эквивалентные определения |лес деревьев]] и позволяет выполнять следующие операции:&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{min(v)}&amp;lt;/tex&amp;gt;''' {{---}} искать минимум на пути от вершины до корня,&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{add(v, c)}&amp;lt;/tex&amp;gt;''' {{---}} прибавлять константу на пути от вершины до корня,&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{link(u, w)}&amp;lt;/tex&amp;gt;''' {{---}} подвешивать одно дерево на другое,&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{cut(v)}&amp;lt;/tex&amp;gt;''' {{---}} отрезать дерево с корнем в вершине &amp;lt;tex&amp;gt;\mathrm{v}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Среднее время выполнения каждой операции {{---}} &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Эта структура данных была придумана Робертом Тарьяном и Даниелем Слейтером в 1982 году.&lt;br /&gt;
&lt;br /&gt;
==Решение задачи в частном случае==&lt;br /&gt;
Сначала рассмотрим частный случай, в котором все деревья {{---}} это пути, и мы хотим уметь:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Path_to_tree.png|250px|thumb|right|Пример построения дерева для пути]]&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{add(v, c)}&amp;lt;/tex&amp;gt;'''  и '''&amp;lt;tex&amp;gt;\mathrm{min(v)}&amp;lt;/tex&amp;gt;''' {{---}} прибавлять константу и искать минимум на некотором суффиксе (то есть на пути от вершины до корня), &lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{cut(v)}&amp;lt;/tex&amp;gt;''' {{---}} разбить один путь на два,&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{link(v, u)}&amp;lt;/tex&amp;gt;''' {{---}} подвешивать голову одного пути к хвосту другого. &lt;br /&gt;
&lt;br /&gt;
Если бы не последние две операции, то можно было бы применить [[Несогласованные поддеревья. Реализация массового обновления|дерево отрезков]], сложив в него вершины в том порядке в котором они идут в пути. Но непонятно, как сливать или разрезать деревья отрезков. Эту задачу можно решить при помощи [[Декартово дерево по неявному ключу|декартового дерева по неявному ключу]]. Также, если использовать какие-нибудь сливаемые деревья, то &amp;lt;tex&amp;gt;\mathrm{link}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{cut}&amp;lt;/tex&amp;gt; реализуются просто. Осталось научиться искать минимум и прибавлять константу на пути. Для этого, как и в деревьях отрезков, будем хранить дополнительные значения в вершинах.&lt;br /&gt;
В качестве сливаемых деревьев выберем [[Splay-дерево|splay-деревья]], в которых ключи выбираются равными глубине вершины. &lt;br /&gt;
&lt;br /&gt;
Тогда операции &amp;lt;tex&amp;gt;\mathrm{cut}&amp;lt;/tex&amp;gt; будет соответствовать &amp;lt;tex&amp;gt;\mathrm{split}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathrm{link(path1, path2)}&amp;lt;/tex&amp;gt; соединяет голову первого пути с хвостом второго. Используем функцию &amp;lt;tex&amp;gt;\mathrm{merge(path2, path1)}&amp;lt;/tex&amp;gt;, которая вызовет &amp;lt;tex&amp;gt;\mathrm{splay}&amp;lt;/tex&amp;gt; от хвоста второго пути и сделает первый путь правым ребенком корня &amp;lt;tex&amp;gt;\mathrm{path2}&amp;lt;/tex&amp;gt;, то есть теперь &amp;lt;tex&amp;gt;\mathrm{path1}&amp;lt;/tex&amp;gt; находится ниже, чем &amp;lt;tex&amp;gt;\mathrm{path2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы прибавлять заданное число на пути от вершины до корня, будем в каждой вершине хранить величину &amp;lt;tex&amp;gt;\Delta w&amp;lt;/tex&amp;gt;, которая равна разнице между весом вершины и весом её родителя. Для корня это значение равно весу самого корня. Поэтому вес вершины определятся следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w(u) = \displaystyle \sum_v^{} \Delta w(v)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; {{---}} все предки вершины &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При прибавлении &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; на пути от вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; до корня, сначала вызывается &amp;lt;tex&amp;gt;\mathrm{splay(v)}&amp;lt;/tex&amp;gt;, после чего в левом поддереве находятся вершины, которые лежат на пути к корню. Затем надо прибавить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; к &amp;lt;tex&amp;gt;\Delta w(v)&amp;lt;/tex&amp;gt; и, чтобы сохранить веса вершин, которые находятся ниже в пути, вычесть &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;\Delta w(right(v))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для реализации &amp;lt;tex&amp;gt;\min&amp;lt;/tex&amp;gt; будем хранить минимум уже для всего поддерева. Чтобы искать минимум от вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, надо вызвать &amp;lt;tex&amp;gt;\mathrm{splay(v)}&amp;lt;/tex&amp;gt; и сравнить её вес с минимумом левого поддерева, в котором теперь находятся все вершины пути кроме &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Определим &amp;lt;tex&amp;gt;\Delta \min (v)&amp;lt;/tex&amp;gt; таким образом, чтобы сохранялся следующий инвариант: &amp;lt;tex&amp;gt;\min (v) = \Delta \min (v) + w(v) &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; дети &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min (v) = \min \{w(v), \min(l), \min(r)\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Delta \min(v) = \min(v) - w(v) \\&lt;br /&gt;
= \min\{w(v) - w(v), \min(l) - w(v), \min(r) - w(v)\} \\&lt;br /&gt;
= \min\{0, \ (\Delta \min(l) + w(l)) - w(v), \ (\Delta \min(r) + w(r)) - w(v)\} \\&lt;br /&gt;
= \min\{0, \ \Delta \min(l) + \Delta w(l), \ \Delta \min(r) + \Delta w(r)\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Linkcut_weights.png|500px]]&lt;br /&gt;
&lt;br /&gt;
==Link-cut tree==&lt;br /&gt;
Чтобы обобщить, разобьем дерево на множество непересекающихся путей. Каждое ребро обозначим либо сплошным, либо пунктирным. Все пути в link-cut дереве хранятся в виде splay-деревьев. Корень каждого splay-дерева хранит указатель на вершину-родителя. В дальнейшем будем называть этот указатель &amp;lt;tex&amp;gt;pathparent&amp;lt;/tex&amp;gt;.&lt;br /&gt;
[[Файл:Linkcut_paths.png|500px||center|Разбиение дерева на пути]]&lt;br /&gt;
&lt;br /&gt;
===expose(u)===&lt;br /&gt;
Ключевая операция в link-cut-деревьях {{---}} &amp;lt;tex&amp;gt;\mathrm{expose(u)}&amp;lt;/tex&amp;gt;. После её выполнения &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; лежит на одном пути с корнем link-cut дерева и при этом становится корнем в splay-дереве получившегося пути. Для этого она поднимается вверх по link-cut дереву, и если какой-нибудь путь пересекает путь от &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; до корня, то она его отрезает, разъединяя splay-дерево и делая соответствующее сплошное ребро пунктирным ребром.&lt;br /&gt;
[[Файл:Linkcut_expose.png|500px||center|Разбиение дерева на пути]]&lt;br /&gt;
&lt;br /&gt;
 '''function''' expose(u: '''tree'''):&lt;br /&gt;
     splay(u)&lt;br /&gt;
     v &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; u&lt;br /&gt;
     '''while''' v &amp;lt;tex&amp;gt; \ne &amp;lt;/tex&amp;gt; root&lt;br /&gt;
         p &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; pathparent(v)        &amp;lt;font color=green&amp;gt;//получаем указатель на ближайшую вершину пути, пересекающего путь от u до корня&amp;lt;/font&amp;gt;&lt;br /&gt;
         splay(p)                  &amp;lt;font color=green&amp;gt;//теперь в правом поддереве p находятся вершины пути, которые находятся ниже чем p в link-cut-дереве,&amp;lt;/font&amp;gt;&lt;br /&gt;
         parent(right(p)) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; null  &amp;lt;font color=green&amp;gt;//поэтому правое поддерево p делаем новым путем&amp;lt;/font&amp;gt;&lt;br /&gt;
         pathparent(right(p)) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; p&lt;br /&gt;
         right(p) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; v             &amp;lt;font color=green&amp;gt;//объединяем оставшийся и построенный пути&amp;lt;/font&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(v) -= &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(p)&lt;br /&gt;
         &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(p) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; min{0, &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(left(p)) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(left(p)), &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(right(p)) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(right(p))}&lt;br /&gt;
         pathparent(v) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; null&lt;br /&gt;
         v &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; p&lt;br /&gt;
     splay(u)&lt;br /&gt;
&lt;br /&gt;
===add(v, c)===&lt;br /&gt;
Чтобы прибавить константу на пути от &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; до корня link-cut-дерева вызовем &amp;lt;tex&amp;gt;\mathrm{expose(v)}&amp;lt;/tex&amp;gt;, что построит запрашиваемый путь в виде splay-дерева, в котором &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; {{---}} корень, и в левом поддереве находятся вершины, которые находятся выше чем &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в link-cut-дереве (то есть все вершины пути без &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;), а в правом {{---}} те, что ниже. Тогда прибавим &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; к &amp;lt;tex&amp;gt;\Delta w(v)&amp;lt;/tex&amp;gt; и вычтем константу от правого ребенка &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, чтобы скомпенсировать разницу и сохранить инвариант.&lt;br /&gt;
&lt;br /&gt;
 '''function''' add(v: '''tree''', c: '''int'''):&lt;br /&gt;
     expose(v)&lt;br /&gt;
     &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(v) += c&lt;br /&gt;
     &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(right(v)) -= c&lt;br /&gt;
&lt;br /&gt;
===min(v)===&lt;br /&gt;
Построим splay-дерево для пути и сравним вес корня &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; c минимумом в левом поддереве:&lt;br /&gt;
 '''function''' min(v: '''tree'''): '''int'''&lt;br /&gt;
     expose(v)&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(left(v)) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(left(v)) &amp;lt; &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(v)&lt;br /&gt;
         '''return''' &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(left(v)) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(left(v))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(v)&lt;br /&gt;
&lt;br /&gt;
===link(v, u)===&lt;br /&gt;
Если &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; {{---}} корень, а &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; {{---}} вершина в другом дереве, то &amp;lt;tex&amp;gt;\mathrm{link(v, u)}&amp;lt;/tex&amp;gt; соединяет два дерева добавлением ребра &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt;, причем &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; становится родителем &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''function''' link(v: '''tree''', u: '''tree'''): '''tree'''&lt;br /&gt;
     expose(v) &amp;lt;font color=green&amp;gt;     //теперь v {{---}} корень в splay-дереве пути и не имеет левого ребенка(так как ключ равен глубине в link-cut дереве)&amp;lt;/font&amp;gt;&lt;br /&gt;
     expose(u)&lt;br /&gt;
     &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(u) -= &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(v) &amp;lt;font color=green&amp;gt;//чтобы сделать u родителем v в link-cut дереве 1. делаем путь, содержащий u, левым ребенком v в splay-дереве&amp;lt;/font&amp;gt;&lt;br /&gt;
     parent(u) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; v &amp;lt;font color=green&amp;gt;//                                              2. обновляем &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w, &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min&amp;lt;/font&amp;gt;&lt;br /&gt;
     left(v) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; u&lt;br /&gt;
     &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(v) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; min{0, &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(u) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(u), &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(right(v)) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w((right(v)))}&lt;br /&gt;
     '''return''' v&lt;br /&gt;
&lt;br /&gt;
===cut(v)===&lt;br /&gt;
Отрезает дерево с корнем &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. После вызова &amp;lt;tex&amp;gt;\mathrm{expose(v)}&amp;lt;/tex&amp;gt; вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; станет корнем splay-дерева, и в правом поддереве будут содержатся все вершины, которые были ниже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в link-cut дереве, а в левом {{---}} те что выше. Обнулив указатель на левого ребенка &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и на родителя в левом поддереве, получим требуемое.&lt;br /&gt;
&lt;br /&gt;
 '''function''' cut(v: '''tree'''):&lt;br /&gt;
     expose(v)&lt;br /&gt;
     &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(left(v)) += &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(v)&lt;br /&gt;
     &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(v) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; min{0, &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;min(right(v)) + &amp;lt;tex&amp;gt;\vartriangle&amp;lt;/tex&amp;gt;w(right(v))}&lt;br /&gt;
     parent(left(v)) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; null&lt;br /&gt;
     left(v) &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; null&lt;br /&gt;
&lt;br /&gt;
==Оценка времени работы==&lt;br /&gt;
Назовем ребро из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в её родителя &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; тяжелым, если количество детей &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; равное &amp;lt;tex&amp;gt;d(u) &amp;gt; \dfrac{1}{2} d(v)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id = Lemma1&lt;br /&gt;
|statement= На пути от вершины до корня не больше &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; легких ребер. &lt;br /&gt;
&lt;br /&gt;
|proof = Пусть &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; {{---}} количество вершин в дереве с корнем в вершине, в которой мы сейчас находимся. Поднимаясь по легкому ребру, &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; увеличивается в два раза, поэтому, пройдя больше &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; легких ребер, получим &amp;lt;tex&amp;gt;m &amp;gt; n&amp;lt;/tex&amp;gt;. Значит, в дереве не больше &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; легких ребер. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Операция &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; осуществляется с помощью последовательности преобразований пунктирного ребра в сплошное ребро и другого сплошного ребра в пунктирное ребро. Обозначим количество таких преобразований за &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Найдем количество преобразований сделанных в течение &amp;lt;tex&amp;gt;\mathrm{expose(u)}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; {{---}} множество всех тяжелых ребер, &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; {{---}} все легкие ребра, &amp;lt;tex&amp;gt;S \rightarrow D&amp;lt;/tex&amp;gt; {{---}} множество сплошных ребер, преобразованных в пунктирные в течение одного &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;D \rightarrow S&amp;lt;/tex&amp;gt; {{---}} множество пунктирных ребер, преобразованных в сплошные.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;M = |\{D \rightarrow S\}| = |\{L \cap D \rightarrow S\}| + |\{H \cap D \rightarrow S\}|&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
По лемме, количество легких пунктирных ребер, преобразованных в сплошные, будет не больше, чем &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; лес деревьев, в которых каждое ребро либо сплошное, либо пунктирное, a &amp;lt;tex&amp;gt;F'&amp;lt;/tex&amp;gt; {{---}} лес, получившийся из &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; после одного вызова &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt;. Определим потенциал &amp;lt;tex&amp;gt;\Phi _{a}(F) = n - 1 - |\{H \cap solid-edges\}|&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\Delta \Phi _{a}&amp;lt;/tex&amp;gt; {{---}} увеличение &amp;lt;tex&amp;gt;\Phi _{a}&amp;lt;/tex&amp;gt; после одной операции &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id = Lemma2&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;V = M + \Delta \Phi _{a} \leqslant 1 + 2\log n &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;V = M + \Delta \Phi _{a}\\&lt;br /&gt;
= M + |H \cap S \rightarrow D| - |H \cap D \rightarrow S| \\&lt;br /&gt;
\leqslant M + |L \cap D \rightarrow S| - |H \cap D \rightarrow S| \\&lt;br /&gt;
= 2 \cdot |L \cap D \rightarrow S| \\&lt;br /&gt;
=2 \cdot \log n&lt;br /&gt;
&amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь проанализируем &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Используя тот факт, что начальное значение &amp;lt;tex&amp;gt;\Phi _{a}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;, приходим к тому, что для деревьев с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, по крайней мере за &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; операцию &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt;, среднее &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; на одну операцию будет не больше, чем &amp;lt;tex&amp;gt;1 + 2\log n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем, что [[Амортизационный анализ|амортизационная стоимость операции]] &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s(v)&amp;lt;/tex&amp;gt; {{---}} количество вершин в поддеревьях &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; ( здесь имеется в виду splay-дерево пути, котоый строится в ходе выполнения &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt;), &amp;lt;tex&amp;gt;r(v) = \log s(v)&amp;lt;/tex&amp;gt;. По  [[Splay-дерево#Lemma1|лемме]] стоимость ''i''-той операции &amp;lt;tex&amp;gt;\mathrm{splay}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;1 + 3 \cdot (r(t) - r(v))&amp;lt;/tex&amp;gt;. Это приводит к тому, что амортизационная стоимость &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt; ограничена следующим значением:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;3 \cdot \log n - 3 \cdot \log (s(v)) + M&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;tex&amp;gt;M = O(\log n)&amp;lt;/tex&amp;gt;, поэтому амортизационная стоимость &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Применение==&lt;br /&gt;
===LCA===&lt;br /&gt;
C помощью link-cut-дерева можно найти наименьшего общего предка:&lt;br /&gt;
 '''function''' lca(u: '''tree''', v: '''tree'''): '''tree'''&lt;br /&gt;
     expose(u)&lt;br /&gt;
     expose(v)&lt;br /&gt;
     '''return''' pathparent(splay(u))&lt;br /&gt;
&lt;br /&gt;
Первый вызов &amp;lt;tex&amp;gt;\mathrm{expose}&amp;lt;/tex&amp;gt; построит путь от &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; до корня. Второй пересечет этот путь в наименьшем общем предке, поэтому в splay-дереве, которому принадлежит &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, хранится указатель &amp;lt;tex&amp;gt;pathparent&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\mathrm{lca}&amp;lt;/tex&amp;gt;, после &amp;lt;tex&amp;gt;\mathrm{splay}(u)&amp;lt;/tex&amp;gt; он будет находиться в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Метод двоичного подъема]]&lt;br /&gt;
* [[Алгоритм Тарьяна поиска LCA за O(1) в оффлайн]]&lt;br /&gt;
* [[Алгоритм Шибера-Вишкина]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/14464 А.С. Станкевич, &amp;quot;Дополнительные главы алгоритмов&amp;quot;]&lt;br /&gt;
* [https://sites.google.com/site/indy256/algo/link-cut-tree-lca Реализация LCA на link-cut дереве]&lt;br /&gt;
* [http://www.cs.cmu.edu/~sleator/papers/dynamic-trees.pdf D. Sleator and R. Tarjan, &amp;quot;A Data Structure for Dynamic Trees&amp;quot;]&lt;br /&gt;
* [http://compgeom.cs.uiuc.edu/~jeffe/teaching/datastructures/2006/notes/07-linkcut.pdf Jeff Erickson. Lecture 7. Link-Cut Trees]&lt;br /&gt;
* [http://planarity.org/Klein_splay_trees_and_link-cut_trees.pdf Optimization Algorithms for Planar Graphs. Splay trees and link-cut trees]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Link/cut_tree Wikipedia {{---}} Link/cut tree]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о наименьшем общем предке]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64689</id>
		<title>Алгоритм отмены цикла минимального среднего веса</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64689"/>
				<updated>2018-03-30T04:27:55Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В статье описывается один из сильно полиномиальных алгоритмов решения [[Поток минимальной стоимости #Задача о потоке минимальной стоимости|задачи о поиске потока минимальной стоимости]].&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
Приведенный алгоритм основан на идее [[Поток минимальной стоимости #Метод устранения отрицательных циклов в остаточной сети|алгоритма Клейна отмены цикла отрицательного веса]]. Выбор цикла минимального среднего веса вместо случайного делает алгоритм сильно полиномиальным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Сильно полиномиальными''' (англ. ''strongly polynomial'') в контексте данной задачи называются алгоритмы, чья сложность полиномиально зависит от &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
===Описание===&lt;br /&gt;
Обозначим как &amp;lt;tex&amp;gt;c_{f}(C)&amp;lt;/tex&amp;gt; остаточную [[Определение сети, потока|пропускную способность]] цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; при протекании в сети потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Cтоимость цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; обозначим за &amp;lt;tex&amp;gt;p(C)&amp;lt;/tex&amp;gt;, а длину (число входящих в него ребер) {{---}} за &amp;lt;tex&amp;gt;\texttt{len}(C)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Средним весом''' (англ. ''mean weight'') цикла будем называть отношение его стоимости к его длине &amp;lt;tex&amp;gt;\mu (C)=\dfrac{p(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;}}&lt;br /&gt;
Данный алгоритм заключается в последовательной отмене циклов минимального среднего веса в [[Дополняющая сеть, дополняющий путь|остаточной сети]] посредством их насыщения. Алгоритм работает до тех пор, пока минимальный средний вес циклов не окажется положительным, что будет означать, что поток минимальной стоимости найден. &lt;br /&gt;
&lt;br /&gt;
Более формально:&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''. Рассмотрим некоторый поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;'''. Найдем цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, обладающий наименьшим средним весом. Если &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости и алгоритм завершается.&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;'''. Отменим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, пустив по нему максимально возможный поток: &amp;lt;tex&amp;gt;f = f + c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;. Перейдем к '''шагу &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
===Сложность===&lt;br /&gt;
Для сетей с целочисленными стоимостями на ребрах &amp;lt;tex&amp;gt;O(VE\cdot VE\log{CV})&amp;lt;/tex&amp;gt;, с вещественными {{---}} &amp;lt;tex&amp;gt;O(VE\cdot VE^{2}\log{V})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В обоих случаях &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; времени тратится на поиск цикла минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
  '''func''' findMin:&lt;br /&gt;
  '''while''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu(C) &amp;lt;/tex&amp;gt;= &amp;lt;tex&amp;gt;\min\limits_c\mu(c)&amp;lt;/tex&amp;gt;            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// &amp;lt;tex&amp;gt;\mu(C)&amp;lt;/tex&amp;gt; {{---}} вес минимального цикла&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// тогда мы нашли f {{---}} поток минимальной стоимости, алгоритм завершается&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''else'''&lt;br /&gt;
      &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; += &amp;lt;tex&amp;gt;c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// иначе отменим цикл&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости. Введём на нашей сети функцию [[Алгоритм Джонсона|потенциалов]] &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Приведённой стоимостью''' (англ. ''reduced cost'') ребра назовем следующую величину: &amp;lt;tex&amp;gt;p_{\varphi}(uv)=\varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
Иными словами, приведённая стоимость {{---}} это сколько нужно потратить денег, чтобы перевезти единицу жидкости из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; (её нужно купить в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, перевезти из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и продать в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости, то &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;\forall uv: \; c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Рассмотрим остаточную сеть {{---}} граф &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В нем нет отрицательных циклов, так как &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости&amp;lt;ref&amp;gt;[[Лемма об эквивалентности свойства потока быть минимальной стоимости и отсутствии отрицательных циклов в остаточной сети]]&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим теперь некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Понятно, что &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p(uv)&amp;lt;/tex&amp;gt;. (Здесь сравниваются минимальный путь &amp;lt;tex&amp;gt;a \rightsquigarrow v&amp;lt;/tex&amp;gt; и путь &amp;lt;tex&amp;gt;a \rightsquigarrow u \rightarrow v&amp;lt;/tex&amp;gt;). Перенеся &amp;lt;tex&amp;gt;\varphi(v)&amp;lt;/tex&amp;gt; в другую часть неравенства, получаем &amp;lt;tex&amp;gt;0 \leqslant \varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;0 \leqslant p_{\varphi}(uv)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Будем говорить, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} '''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-optimal''), если &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt;\forall uv: c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если стоимости целочисленны и поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, где &amp;lt;tex&amp;gt;\varepsilon &amp;lt; \dfrac{1}{V}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.&lt;br /&gt;
|proof= &lt;br /&gt;
:Рассмотрим цикл в остаточной сети &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;p(C)=p_{\varphi}(C)&amp;lt;/tex&amp;gt; (для доказательства этого факта достаточно расписать &amp;lt;tex&amp;gt;p_{\varphi}(C)&amp;lt;/tex&amp;gt; по определению).&lt;br /&gt;
&lt;br /&gt;
:Возьмем &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; такое, что стоимости всех ребер в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;-\varepsilon&amp;lt;/tex&amp;gt;. Тогда стоимость всего цикла &amp;lt;tex&amp;gt;p_{\varphi}(C)\geqslant -V\cdot \varepsilon&amp;lt;/tex&amp;gt; (в цикле не больше &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; ребер). Таким образом, &amp;lt;tex&amp;gt;p_{\varphi}(C) &amp;gt; -1&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p(C) &amp;gt; -1&amp;lt;/tex&amp;gt;. Но исходные пропускные способности были целочисленными, поэтому &amp;lt;tex&amp;gt;p(C) \geqslant 0&amp;lt;/tex&amp;gt;, а это означает, что в остаточной сети нет отрицательных циклов, и, соответственно, &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.}}&lt;br /&gt;
&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимальную величину среди средних весов циклов для потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, а за &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток не минимальной стоимости, то &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса в остаточной сети.&lt;br /&gt;
*Покажем, что &amp;lt;tex&amp;gt;\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Поскольку поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальным, верно следующее: &amp;lt;tex&amp;gt;p(C) = p_{\varphi}(C) \geqslant -\texttt{len}(C) \cdot \varepsilon^{*}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\dfrac{p(C)}{\texttt{len}(C)} \geqslant -\varepsilon^{*} &amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;\mu(C)=\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Теперь покажем, что &amp;lt;tex&amp;gt;\mu^{*} \leqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;p'(uv)=p(uv)-\mu^{*}&amp;lt;/tex&amp;gt; для любого &amp;lt;tex&amp;gt;uv \in E_{f}&amp;lt;/tex&amp;gt;. Логичным будет также обозначить для некоторого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;\mu'(C)&amp;lt;/tex&amp;gt; величину &amp;lt;tex&amp;gt;\dfrac{p'(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;. Таким образом, для любого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mu'(C)=\mu(C)-\mu^{*}\geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость (считая стоимостью функцию &amp;lt;tex&amp;gt;p'&amp;lt;/tex&amp;gt;) минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Таким образом, &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}&amp;lt;/tex&amp;gt;. Отсюда получаем, что &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt; для любого ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; из остаточной сети &amp;lt;tex&amp;gt;E_{f}&amp;lt;/tex&amp;gt;, что означает, что &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;(-\mu^{*})&amp;lt;/tex&amp;gt;-оптимальный, и, по определению &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\varepsilon^{*} \leqslant -\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Отмена цикла минимального среднего веса не увеличивает &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальности: &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]], &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt;. Но поскольку &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; {{---}} средний вес цикла, то &amp;lt;tex&amp;gt;p_{\varphi}(uv) = \mu^{*} = -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, в остаточной сети появятся ребра стоимости &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Таким образом, свойство &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt; все еще выполняется.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Допустимым графом''' (англ. ''admissible graph'') будем называть такой подграф остаточной сети, что он включает только ребра отрицательной приведенной стоимости. &amp;lt;tex&amp;gt;H=\{uv \in E_{f}\;|\; p_{\varphi}(uv) &amp;lt; 0\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} некоторый поток, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} поток после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен циклов минимального среднего веса. Тогда &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; {{---}} минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
|proof=&lt;br /&gt;
:Изначально любое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. Отмена цикла добавляет в остаточную сеть &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt; только ребра положительной приведенной стоимости (см. [[#lemma4|лемму &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]) и удаляет из сети &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; как минимум одно ребро. Рассмотрим два случая:&lt;br /&gt;
:#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; и после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен граф &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; пуст, что означает, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} оптимальный поток, то есть &amp;lt;tex&amp;gt;\varepsilon'^{*}=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой итерации, и, соответственно, &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; {{---}} первый из таких циклов. Для &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; имеем, что каждое его ребро обладает приведенной стоимостью как минимум &amp;lt;tex&amp;gt;-\varepsilon_{i}^{*}&amp;lt;/tex&amp;gt; (при этом &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}&amp;lt;/tex&amp;gt; по [[#lemma4|лемме &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]), хотя бы одно из ребер &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; обладает неотрицательной приведенной стоимостью и количество ребер в &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; не превышает &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;. Тогда средний вес этого цикла &amp;lt;tex&amp;gt;\mu(C_{i}) = \mu_{i}^{*} \geqslant -\left(1-\dfrac{1}{V}\right)\varepsilon_{i}^{*} \geqslant - \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} = -\mu_{i}^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксированным''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-fixed'') будем называть ребро, поток через которое неизменен для любых &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальных потоков в сети.}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=theorem1&lt;br /&gt;
|statement=Пусть поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальным с функцией потенциалов &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;. Также пусть для некоторого ребра &amp;lt;tex&amp;gt;uv \; \left|p_{\varphi}(uv)\right| \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;. Тогда ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксировано.&lt;br /&gt;
|proof=&lt;br /&gt;
:По свойству антисимметричности, достаточно будет доказать теорему для случая &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим такой поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon &amp;gt; \varepsilon&amp;lt;/tex&amp;gt;, поток по ребру &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; должен быть как можно меньше, то есть &amp;lt;tex&amp;gt;f(uv) = -c(uv)&amp;lt;/tex&amp;gt;, и тогда раз &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f'(uv) &amp;gt; f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Покажем теперь, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
:Обозначим за &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; подграф &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; такой, что &amp;lt;tex&amp;gt;G_{&amp;gt;}=(V, \{uv \in E \;|\; f'(uv) &amp;gt; f(uv) \})&amp;lt;/tex&amp;gt;. Рассмотрим некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; являются циркуляциями, в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; должен содержаться простой цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, проходящий через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Поскольку все ребра в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} остаточные, стоимость &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon &amp;gt; V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Теперь рассмотрим цикл &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt;, который получен из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; разворотом всех его ребер. Заметим, что &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; является циклом в &amp;lt;tex&amp;gt;G_{&amp;lt;}=(V,\{uv \in E \;|\; f'(uv) &amp;lt; f(uv)\})&amp;lt;/tex&amp;gt; и, соответственно, циклом в &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. По свойству антисимметричности, стоимость &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; меньше, чем &amp;lt;tex&amp;gt;-V\varepsilon&amp;lt;/tex&amp;gt; и, таким образом, &amp;lt;tex&amp;gt;\mu(\overline{C}) &amp;lt; -\varepsilon&amp;lt;/tex&amp;gt;. Откуда по [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]] имеем, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимален.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=доказательство оценки времени работы алгоритма в случае вещественных стоимостей&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;k=VE(\lceil \log V + 1 \rceil)&amp;lt;/tex&amp;gt;. Разобьем работу алгоритма на группы по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; последовательных итераций. Утверждается, что каждая группа фиксирует поток на независимом ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, то есть итерации из другой группы не меняют величину &amp;lt;tex&amp;gt;f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Оценка времени работы следует непосредственно из этого утверждения. &lt;br /&gt;
:Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток до первой итерации, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} после последней итерации этой группы. Обозначим за &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, а за &amp;lt;tex&amp;gt;\varphi'&amp;lt;/tex&amp;gt; {{---}} функцию потенциалов такую, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt;-оптимальности. Выбор &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и [[#lemma5|лемма &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;]] дают нам следующее неравенство: &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon^{*} \left(1-\dfrac{1}{V} \right)^{V(\log V + 1)} \leqslant \dfrac{\varepsilon^{*}}{2V}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Рассмотрим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;-\varepsilon^{*}&amp;lt;/tex&amp;gt; (см. [[#lemma3|лемму &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]]), некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; должно иметь приведенную стоимость &amp;lt;tex&amp;gt;p_{\varphi'}(uv) \leqslant -\varepsilon^{*} \leqslant -2V\varepsilon'^{*}&amp;lt;/tex&amp;gt;. Таким образом, поток на ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; не изменится при итерациях, происходящих после этой группы. Таким образом, по [[#theorem1|теореме]] каждая группа фиксирует поток на независимом ребре.}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм поиска цикла минимального среднего веса==&lt;br /&gt;
===Наивный способ===&lt;br /&gt;
Устроим [[Вещественный двоичный поиск |двоичный поиск]].&lt;br /&gt;
Установим нижнюю и верхнюю границы величины среднего веса цикла &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; соответственно, вычислим серединное значение &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; и отнимем полученную величину &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; от всех ребер сети. Если теперь в нашей сети есть отрицательный цикл (этот факт можно проверить при помощи [[Алгоритм Форда-Беллмана #Нахождение отрицательного цикла|алгоритма Форда-Беллмана]]), значит существует цикл с меньшим средним весом, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Тогда продолжим поиск среди значений в диапазоне от &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, иначе {{---}} от &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда, если &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C_{min}&amp;lt;/tex&amp;gt; {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за &amp;lt;tex&amp;gt;O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; {{---}} точность выбора среднего веса цикла.&lt;br /&gt;
При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить &amp;lt;tex&amp;gt;\dfrac{1}{V}&amp;lt;/tex&amp;gt;, что дает нам оценку &amp;lt;tex&amp;gt;O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
    '''func''' findMinCycleBinarySearch (l, r):&lt;br /&gt;
      m = (l + r) / &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' e : edges&lt;br /&gt;
        e.weight -= m&lt;br /&gt;
      '''if''' &amp;lt;tex&amp;gt;\exists C&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu (C) &amp;lt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findMinCycleBinarySearch (l, m)&lt;br /&gt;
      '''else'''&lt;br /&gt;
        findMinCycleBinarySearch (m, r)&lt;br /&gt;
&lt;br /&gt;
===Продвинутый алгоритм===&lt;br /&gt;
Добавим к нашему графу вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и ребра из нее во все остальные вершины.&lt;br /&gt;
Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: &amp;lt;tex&amp;gt;d[i][u]&amp;lt;/tex&amp;gt; {{---}} длина минимального пути от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; ровно из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
Тогда длина оптимального цикла &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимального среднего веса вычисляется как &amp;lt;tex&amp;gt;\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достаточно будет доказать это правило для &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;, так как для других &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; можно просто отнять эту величину от всех ребер и получить снова случай с &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы найти цикл после построения матрицы &amp;lt;tex&amp;gt;d[k][u]&amp;lt;/tex&amp;gt;, запомним, при каких &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; достигается оптимальное значение &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt;, и, используя &amp;lt;tex&amp;gt;d[n][u]&amp;lt;/tex&amp;gt;, поднимемся по указателям предков. Как только мы попадем в уже посещенную вершину {{---}} мы нашли цикл минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм работает за &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; &amp;lt;ref&amp;gt;[[Алгоритм Форда-Беллмана #Сложность| Сложность алгоритма Форда-Беллмана]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  '''func''' findMinCycle:&lt;br /&gt;
    '''Node''' s&lt;br /&gt;
    '''Edge''' e&lt;br /&gt;
    insert(s)                                         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// добавляем мнимую вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и проводим рёбра нулевого веса в каждую вершину графа&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' u '''in''' &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
      e.begin = s&lt;br /&gt;
      e.end = u&lt;br /&gt;
      e.weight = &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    fordBellman(s)&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mu^{*} = \min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&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;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://youtu.be/bykbw7HovSo?t=4287 Лекция 14 | Дополнительные главы алгоритмов | Андрей Станкевич | CSC | Лекториум]&lt;br /&gt;
* [http://sirius.cs.put.poznan.pl/~inf84789/acm/p873-goldberg.pdf A.V.Goldberg and R.E.Tarjan {{---}} Finding Minimum-Cost Circulations by Cancelling Negative Cycles (Journal of the Association for Computing Machinery. Vol. 36, No. 4. October 1989. pp. 873-886.)]&lt;br /&gt;
*[https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-854j-advanced-algorithms-fall-2008/lecture-notes/lec4.pdf Lecture by M.X.Goemans on Goldberg-Tarjan Min-Cost Circulation Algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64688</id>
		<title>Алгоритм отмены цикла минимального среднего веса</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64688"/>
				<updated>2018-03-30T04:26:32Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В статье описывается один из сильно полиномиальных алгоритмов решения [[Поток минимальной стоимости #Задача о потоке минимальной стоимости|задачи о поиске потока минимальной стоимости]].&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
Приведенный алгоритм основан на идее [[Поток минимальной стоимости #Метод устранения отрицательных циклов в остаточной сети|алгоритма Клейна отмены цикла отрицательного веса]]. Выбор цикла минимального среднего веса вместо случайного делает алгоритм сильно полиномиальным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Сильно полиномиальными''' (англ. ''strongly polynomial'') в контексте данной задачи называются алгоритмы, чья сложность полиномиально зависит от &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
===Описание===&lt;br /&gt;
Обозначим как &amp;lt;tex&amp;gt;c_{f}(C)&amp;lt;/tex&amp;gt; остаточную [[Определение сети, потока|пропускную способность]] цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; при протекании в сети потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Cтоимость цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; обозначим за &amp;lt;tex&amp;gt;p(C)&amp;lt;/tex&amp;gt;, а длину (число входящих в него ребер) {{---}} за &amp;lt;tex&amp;gt;\texttt{len}(C)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Средним весом''' (англ. ''mean weight'') цикла будем называть отношение его стоимости к его длине &amp;lt;tex&amp;gt;\mu (C)=\dfrac{p(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;}}&lt;br /&gt;
Данный алгоритм заключается в последовательной отмене циклов минимального среднего веса в [[Дополняющая сеть, дополняющий путь|остаточной сети]] посредством их насыщения. Алгоритм работает до тех пор, пока минимальный средний вес циклов не окажется положительным, что будет означать, что поток минимальной стоимости найден. &lt;br /&gt;
&lt;br /&gt;
Более формально:&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''. Рассмотрим некоторый поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;'''. Найдем цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, обладающий наименьшим средним весом. Если &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости и алгоритм завершается.&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;'''. Отменим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, пустив по нему максимально возможный поток: &amp;lt;tex&amp;gt;f = f + c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;. Перейдем к '''шагу &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
===Сложность===&lt;br /&gt;
Для сетей с целочисленными стоимостями на ребрах &amp;lt;tex&amp;gt;O(VE\cdot VE\log{CV})&amp;lt;/tex&amp;gt;, с вещественными {{---}} &amp;lt;tex&amp;gt;O(VE\cdot VE^{2}\log{V})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В обоих случаях &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; времени тратится на поиск цикла минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
  '''func''' findMin:&lt;br /&gt;
  '''while''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu(C) &amp;lt;/tex&amp;gt;= &amp;lt;tex&amp;gt;\mathrm{min}\mu(c)&amp;lt;/tex&amp;gt;            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// &amp;lt;tex&amp;gt;\mu(C)&amp;lt;/tex&amp;gt; {{---}} вес минимального цикла&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// тогда мы нашли f {{---}} поток минимальной стоимости, алгоритм завершается&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''else'''&lt;br /&gt;
      &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; += &amp;lt;tex&amp;gt;c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// иначе отменим цикл&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости. Введём на нашей сети функцию [[Алгоритм Джонсона|потенциалов]] &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Приведённой стоимостью''' (англ. ''reduced cost'') ребра назовем следующую величину: &amp;lt;tex&amp;gt;p_{\varphi}(uv)=\varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
Иными словами, приведённая стоимость {{---}} это сколько нужно потратить денег, чтобы перевезти единицу жидкости из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; (её нужно купить в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, перевезти из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и продать в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости, то &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;\forall uv: \; c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Рассмотрим остаточную сеть {{---}} граф &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В нем нет отрицательных циклов, так как &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости&amp;lt;ref&amp;gt;[[Лемма об эквивалентности свойства потока быть минимальной стоимости и отсутствии отрицательных циклов в остаточной сети]]&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим теперь некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Понятно, что &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p(uv)&amp;lt;/tex&amp;gt;. (Здесь сравниваются минимальный путь &amp;lt;tex&amp;gt;a \rightsquigarrow v&amp;lt;/tex&amp;gt; и путь &amp;lt;tex&amp;gt;a \rightsquigarrow u \rightarrow v&amp;lt;/tex&amp;gt;). Перенеся &amp;lt;tex&amp;gt;\varphi(v)&amp;lt;/tex&amp;gt; в другую часть неравенства, получаем &amp;lt;tex&amp;gt;0 \leqslant \varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;0 \leqslant p_{\varphi}(uv)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Будем говорить, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} '''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-optimal''), если &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt;\forall uv: c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если стоимости целочисленны и поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, где &amp;lt;tex&amp;gt;\varepsilon &amp;lt; \dfrac{1}{V}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.&lt;br /&gt;
|proof= &lt;br /&gt;
:Рассмотрим цикл в остаточной сети &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;p(C)=p_{\varphi}(C)&amp;lt;/tex&amp;gt; (для доказательства этого факта достаточно расписать &amp;lt;tex&amp;gt;p_{\varphi}(C)&amp;lt;/tex&amp;gt; по определению).&lt;br /&gt;
&lt;br /&gt;
:Возьмем &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; такое, что стоимости всех ребер в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;-\varepsilon&amp;lt;/tex&amp;gt;. Тогда стоимость всего цикла &amp;lt;tex&amp;gt;p_{\varphi}(C)\geqslant -V\cdot \varepsilon&amp;lt;/tex&amp;gt; (в цикле не больше &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; ребер). Таким образом, &amp;lt;tex&amp;gt;p_{\varphi}(C) &amp;gt; -1&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p(C) &amp;gt; -1&amp;lt;/tex&amp;gt;. Но исходные пропускные способности были целочисленными, поэтому &amp;lt;tex&amp;gt;p(C) \geqslant 0&amp;lt;/tex&amp;gt;, а это означает, что в остаточной сети нет отрицательных циклов, и, соответственно, &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.}}&lt;br /&gt;
&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимальную величину среди средних весов циклов для потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, а за &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток не минимальной стоимости, то &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса в остаточной сети.&lt;br /&gt;
*Покажем, что &amp;lt;tex&amp;gt;\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Поскольку поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальным, верно следующее: &amp;lt;tex&amp;gt;p(C) = p_{\varphi}(C) \geqslant -\texttt{len}(C) \cdot \varepsilon^{*}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\dfrac{p(C)}{\texttt{len}(C)} \geqslant -\varepsilon^{*} &amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;\mu(C)=\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Теперь покажем, что &amp;lt;tex&amp;gt;\mu^{*} \leqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;p'(uv)=p(uv)-\mu^{*}&amp;lt;/tex&amp;gt; для любого &amp;lt;tex&amp;gt;uv \in E_{f}&amp;lt;/tex&amp;gt;. Логичным будет также обозначить для некоторого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;\mu'(C)&amp;lt;/tex&amp;gt; величину &amp;lt;tex&amp;gt;\dfrac{p'(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;. Таким образом, для любого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mu'(C)=\mu(C)-\mu^{*}\geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость (считая стоимостью функцию &amp;lt;tex&amp;gt;p'&amp;lt;/tex&amp;gt;) минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Таким образом, &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}&amp;lt;/tex&amp;gt;. Отсюда получаем, что &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt; для любого ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; из остаточной сети &amp;lt;tex&amp;gt;E_{f}&amp;lt;/tex&amp;gt;, что означает, что &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;(-\mu^{*})&amp;lt;/tex&amp;gt;-оптимальный, и, по определению &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\varepsilon^{*} \leqslant -\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Отмена цикла минимального среднего веса не увеличивает &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальности: &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]], &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt;. Но поскольку &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; {{---}} средний вес цикла, то &amp;lt;tex&amp;gt;p_{\varphi}(uv) = \mu^{*} = -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, в остаточной сети появятся ребра стоимости &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Таким образом, свойство &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt; все еще выполняется.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Допустимым графом''' (англ. ''admissible graph'') будем называть такой подграф остаточной сети, что он включает только ребра отрицательной приведенной стоимости. &amp;lt;tex&amp;gt;H=\{uv \in E_{f}\;|\; p_{\varphi}(uv) &amp;lt; 0\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} некоторый поток, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} поток после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен циклов минимального среднего веса. Тогда &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; {{---}} минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
|proof=&lt;br /&gt;
:Изначально любое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. Отмена цикла добавляет в остаточную сеть &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt; только ребра положительной приведенной стоимости (см. [[#lemma4|лемму &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]) и удаляет из сети &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; как минимум одно ребро. Рассмотрим два случая:&lt;br /&gt;
:#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; и после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен граф &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; пуст, что означает, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} оптимальный поток, то есть &amp;lt;tex&amp;gt;\varepsilon'^{*}=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой итерации, и, соответственно, &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; {{---}} первый из таких циклов. Для &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; имеем, что каждое его ребро обладает приведенной стоимостью как минимум &amp;lt;tex&amp;gt;-\varepsilon_{i}^{*}&amp;lt;/tex&amp;gt; (при этом &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}&amp;lt;/tex&amp;gt; по [[#lemma4|лемме &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]), хотя бы одно из ребер &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; обладает неотрицательной приведенной стоимостью и количество ребер в &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; не превышает &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;. Тогда средний вес этого цикла &amp;lt;tex&amp;gt;\mu(C_{i}) = \mu_{i}^{*} \geqslant -\left(1-\dfrac{1}{V}\right)\varepsilon_{i}^{*} \geqslant - \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} = -\mu_{i}^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксированным''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-fixed'') будем называть ребро, поток через которое неизменен для любых &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальных потоков в сети.}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=theorem1&lt;br /&gt;
|statement=Пусть поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальным с функцией потенциалов &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;. Также пусть для некоторого ребра &amp;lt;tex&amp;gt;uv \; \left|p_{\varphi}(uv)\right| \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;. Тогда ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксировано.&lt;br /&gt;
|proof=&lt;br /&gt;
:По свойству антисимметричности, достаточно будет доказать теорему для случая &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим такой поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon &amp;gt; \varepsilon&amp;lt;/tex&amp;gt;, поток по ребру &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; должен быть как можно меньше, то есть &amp;lt;tex&amp;gt;f(uv) = -c(uv)&amp;lt;/tex&amp;gt;, и тогда раз &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f'(uv) &amp;gt; f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Покажем теперь, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
:Обозначим за &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; подграф &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; такой, что &amp;lt;tex&amp;gt;G_{&amp;gt;}=(V, \{uv \in E \;|\; f'(uv) &amp;gt; f(uv) \})&amp;lt;/tex&amp;gt;. Рассмотрим некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; являются циркуляциями, в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; должен содержаться простой цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, проходящий через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Поскольку все ребра в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} остаточные, стоимость &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon &amp;gt; V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Теперь рассмотрим цикл &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt;, который получен из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; разворотом всех его ребер. Заметим, что &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; является циклом в &amp;lt;tex&amp;gt;G_{&amp;lt;}=(V,\{uv \in E \;|\; f'(uv) &amp;lt; f(uv)\})&amp;lt;/tex&amp;gt; и, соответственно, циклом в &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. По свойству антисимметричности, стоимость &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; меньше, чем &amp;lt;tex&amp;gt;-V\varepsilon&amp;lt;/tex&amp;gt; и, таким образом, &amp;lt;tex&amp;gt;\mu(\overline{C}) &amp;lt; -\varepsilon&amp;lt;/tex&amp;gt;. Откуда по [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]] имеем, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимален.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=доказательство оценки времени работы алгоритма в случае вещественных стоимостей&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;k=VE(\lceil \log V + 1 \rceil)&amp;lt;/tex&amp;gt;. Разобьем работу алгоритма на группы по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; последовательных итераций. Утверждается, что каждая группа фиксирует поток на независимом ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, то есть итерации из другой группы не меняют величину &amp;lt;tex&amp;gt;f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Оценка времени работы следует непосредственно из этого утверждения. &lt;br /&gt;
:Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток до первой итерации, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} после последней итерации этой группы. Обозначим за &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, а за &amp;lt;tex&amp;gt;\varphi'&amp;lt;/tex&amp;gt; {{---}} функцию потенциалов такую, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt;-оптимальности. Выбор &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и [[#lemma5|лемма &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;]] дают нам следующее неравенство: &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon^{*} \left(1-\dfrac{1}{V} \right)^{V(\log V + 1)} \leqslant \dfrac{\varepsilon^{*}}{2V}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Рассмотрим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;-\varepsilon^{*}&amp;lt;/tex&amp;gt; (см. [[#lemma3|лемму &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]]), некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; должно иметь приведенную стоимость &amp;lt;tex&amp;gt;p_{\varphi'}(uv) \leqslant -\varepsilon^{*} \leqslant -2V\varepsilon'^{*}&amp;lt;/tex&amp;gt;. Таким образом, поток на ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; не изменится при итерациях, происходящих после этой группы. Таким образом, по [[#theorem1|теореме]] каждая группа фиксирует поток на независимом ребре.}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм поиска цикла минимального среднего веса==&lt;br /&gt;
===Наивный способ===&lt;br /&gt;
Устроим [[Вещественный двоичный поиск |двоичный поиск]].&lt;br /&gt;
Установим нижнюю и верхнюю границы величины среднего веса цикла &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; соответственно, вычислим серединное значение &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; и отнимем полученную величину &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; от всех ребер сети. Если теперь в нашей сети есть отрицательный цикл (этот факт можно проверить при помощи [[Алгоритм Форда-Беллмана #Нахождение отрицательного цикла|алгоритма Форда-Беллмана]]), значит существует цикл с меньшим средним весом, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Тогда продолжим поиск среди значений в диапазоне от &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, иначе {{---}} от &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда, если &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C_{min}&amp;lt;/tex&amp;gt; {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за &amp;lt;tex&amp;gt;O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; {{---}} точность выбора среднего веса цикла.&lt;br /&gt;
При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить &amp;lt;tex&amp;gt;\dfrac{1}{V}&amp;lt;/tex&amp;gt;, что дает нам оценку &amp;lt;tex&amp;gt;O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
    '''func''' findMinCycleBinarySearch (l, r):&lt;br /&gt;
      m = (l + r) / &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' e : edges&lt;br /&gt;
        e.weight -= m&lt;br /&gt;
      '''if''' &amp;lt;tex&amp;gt;\exists C&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu (C) &amp;lt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findMinCycleBinarySearch (l, m)&lt;br /&gt;
      '''else'''&lt;br /&gt;
        findMinCycleBinarySearch (m, r)&lt;br /&gt;
&lt;br /&gt;
===Продвинутый алгоритм===&lt;br /&gt;
Добавим к нашему графу вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и ребра из нее во все остальные вершины.&lt;br /&gt;
Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: &amp;lt;tex&amp;gt;d[i][u]&amp;lt;/tex&amp;gt; {{---}} длина минимального пути от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; ровно из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
Тогда длина оптимального цикла &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимального среднего веса вычисляется как &amp;lt;tex&amp;gt;\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достаточно будет доказать это правило для &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;, так как для других &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; можно просто отнять эту величину от всех ребер и получить снова случай с &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы найти цикл после построения матрицы &amp;lt;tex&amp;gt;d[k][u]&amp;lt;/tex&amp;gt;, запомним, при каких &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; достигается оптимальное значение &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt;, и, используя &amp;lt;tex&amp;gt;d[n][u]&amp;lt;/tex&amp;gt;, поднимемся по указателям предков. Как только мы попадем в уже посещенную вершину {{---}} мы нашли цикл минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм работает за &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; &amp;lt;ref&amp;gt;[[Алгоритм Форда-Беллмана #Сложность| Сложность алгоритма Форда-Беллмана]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  '''func''' findMinCycle:&lt;br /&gt;
    '''Node''' s&lt;br /&gt;
    '''Edge''' e&lt;br /&gt;
    insert(s)                                         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// добавляем мнимую вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и проводим рёбра нулевого веса в каждую вершину графа&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' u '''in''' &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
      e.begin = s&lt;br /&gt;
      e.end = u&lt;br /&gt;
      e.weight = &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    fordBellman(s)&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mu^{*} = \min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&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;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://youtu.be/bykbw7HovSo?t=4287 Лекция 14 | Дополнительные главы алгоритмов | Андрей Станкевич | CSC | Лекториум]&lt;br /&gt;
* [http://sirius.cs.put.poznan.pl/~inf84789/acm/p873-goldberg.pdf A.V.Goldberg and R.E.Tarjan {{---}} Finding Minimum-Cost Circulations by Cancelling Negative Cycles (Journal of the Association for Computing Machinery. Vol. 36, No. 4. October 1989. pp. 873-886.)]&lt;br /&gt;
*[https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-854j-advanced-algorithms-fall-2008/lecture-notes/lec4.pdf Lecture by M.X.Goemans on Goldberg-Tarjan Min-Cost Circulation Algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64687</id>
		<title>Алгоритм отмены цикла минимального среднего веса</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64687"/>
				<updated>2018-03-30T04:25:33Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В статье описывается один из сильно полиномиальных алгоритмов решения [[Поток минимальной стоимости #Задача о потоке минимальной стоимости|задачи о поиске потока минимальной стоимости]].&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
Приведенный алгоритм основан на идее [[Поток минимальной стоимости #Метод устранения отрицательных циклов в остаточной сети|алгоритма Клейна отмены цикла отрицательного веса]]. Выбор цикла минимального среднего веса вместо случайного делает алгоритм сильно полиномиальным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Сильно полиномиальными''' (англ. ''strongly polynomial'') в контексте данной задачи называются алгоритмы, чья сложность полиномиально зависит от &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
===Описание===&lt;br /&gt;
Обозначим как &amp;lt;tex&amp;gt;c_{f}(C)&amp;lt;/tex&amp;gt; остаточную [[Определение сети, потока|пропускную способность]] цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; при протекании в сети потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Cтоимость цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; обозначим за &amp;lt;tex&amp;gt;p(C)&amp;lt;/tex&amp;gt;, а длину (число входящих в него ребер) {{---}} за &amp;lt;tex&amp;gt;\texttt{len}(C)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Средним весом''' (англ. ''mean weight'') цикла будем называть отношение его стоимости к его длине &amp;lt;tex&amp;gt;\mu (C)=\dfrac{p(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;}}&lt;br /&gt;
Данный алгоритм заключается в последовательной отмене циклов минимального среднего веса в [[Дополняющая сеть, дополняющий путь|остаточной сети]] посредством их насыщения. Алгоритм работает до тех пор, пока минимальный средний вес циклов не окажется положительным, что будет означать, что поток минимальной стоимости найден. &lt;br /&gt;
&lt;br /&gt;
Более формально:&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''. Рассмотрим некоторый поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;'''. Найдем цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, обладающий наименьшим средним весом. Если &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости и алгоритм завершается.&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;'''. Отменим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, пустив по нему максимально возможный поток: &amp;lt;tex&amp;gt;f = f + c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;. Перейдем к '''шагу &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
===Сложность===&lt;br /&gt;
Для сетей с целочисленными стоимостями на ребрах &amp;lt;tex&amp;gt;O(VE\cdot VE\log{CV})&amp;lt;/tex&amp;gt;, с вещественными {{---}} &amp;lt;tex&amp;gt;O(VE\cdot VE^{2}\log{V})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В обоих случаях &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; времени тратится на поиск цикла минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
  '''func''' findMin:&lt;br /&gt;
  '''while''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu(C) &amp;lt;/tex&amp;gt;= &amp;lt;tex&amp;gt;\mathrm{min}\limits_c \mu(c)&amp;lt;/tex&amp;gt;            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// &amp;lt;tex&amp;gt;\mu(C)&amp;lt;/tex&amp;gt; {{---}} вес минимального цикла&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// тогда мы нашли f {{---}} поток минимальной стоимости, алгоритм завершается&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''else'''&lt;br /&gt;
      &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; += &amp;lt;tex&amp;gt;c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// иначе отменим цикл&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости. Введём на нашей сети функцию [[Алгоритм Джонсона|потенциалов]] &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Приведённой стоимостью''' (англ. ''reduced cost'') ребра назовем следующую величину: &amp;lt;tex&amp;gt;p_{\varphi}(uv)=\varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
Иными словами, приведённая стоимость {{---}} это сколько нужно потратить денег, чтобы перевезти единицу жидкости из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; (её нужно купить в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, перевезти из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и продать в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости, то &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;\forall uv: \; c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Рассмотрим остаточную сеть {{---}} граф &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В нем нет отрицательных циклов, так как &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости&amp;lt;ref&amp;gt;[[Лемма об эквивалентности свойства потока быть минимальной стоимости и отсутствии отрицательных циклов в остаточной сети]]&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим теперь некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Понятно, что &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p(uv)&amp;lt;/tex&amp;gt;. (Здесь сравниваются минимальный путь &amp;lt;tex&amp;gt;a \rightsquigarrow v&amp;lt;/tex&amp;gt; и путь &amp;lt;tex&amp;gt;a \rightsquigarrow u \rightarrow v&amp;lt;/tex&amp;gt;). Перенеся &amp;lt;tex&amp;gt;\varphi(v)&amp;lt;/tex&amp;gt; в другую часть неравенства, получаем &amp;lt;tex&amp;gt;0 \leqslant \varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;0 \leqslant p_{\varphi}(uv)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Будем говорить, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} '''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-optimal''), если &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt;\forall uv: c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если стоимости целочисленны и поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, где &amp;lt;tex&amp;gt;\varepsilon &amp;lt; \dfrac{1}{V}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.&lt;br /&gt;
|proof= &lt;br /&gt;
:Рассмотрим цикл в остаточной сети &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;p(C)=p_{\varphi}(C)&amp;lt;/tex&amp;gt; (для доказательства этого факта достаточно расписать &amp;lt;tex&amp;gt;p_{\varphi}(C)&amp;lt;/tex&amp;gt; по определению).&lt;br /&gt;
&lt;br /&gt;
:Возьмем &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; такое, что стоимости всех ребер в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;-\varepsilon&amp;lt;/tex&amp;gt;. Тогда стоимость всего цикла &amp;lt;tex&amp;gt;p_{\varphi}(C)\geqslant -V\cdot \varepsilon&amp;lt;/tex&amp;gt; (в цикле не больше &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; ребер). Таким образом, &amp;lt;tex&amp;gt;p_{\varphi}(C) &amp;gt; -1&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p(C) &amp;gt; -1&amp;lt;/tex&amp;gt;. Но исходные пропускные способности были целочисленными, поэтому &amp;lt;tex&amp;gt;p(C) \geqslant 0&amp;lt;/tex&amp;gt;, а это означает, что в остаточной сети нет отрицательных циклов, и, соответственно, &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.}}&lt;br /&gt;
&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимальную величину среди средних весов циклов для потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, а за &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток не минимальной стоимости, то &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса в остаточной сети.&lt;br /&gt;
*Покажем, что &amp;lt;tex&amp;gt;\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Поскольку поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальным, верно следующее: &amp;lt;tex&amp;gt;p(C) = p_{\varphi}(C) \geqslant -\texttt{len}(C) \cdot \varepsilon^{*}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\dfrac{p(C)}{\texttt{len}(C)} \geqslant -\varepsilon^{*} &amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;\mu(C)=\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Теперь покажем, что &amp;lt;tex&amp;gt;\mu^{*} \leqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;p'(uv)=p(uv)-\mu^{*}&amp;lt;/tex&amp;gt; для любого &amp;lt;tex&amp;gt;uv \in E_{f}&amp;lt;/tex&amp;gt;. Логичным будет также обозначить для некоторого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;\mu'(C)&amp;lt;/tex&amp;gt; величину &amp;lt;tex&amp;gt;\dfrac{p'(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;. Таким образом, для любого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mu'(C)=\mu(C)-\mu^{*}\geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость (считая стоимостью функцию &amp;lt;tex&amp;gt;p'&amp;lt;/tex&amp;gt;) минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Таким образом, &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}&amp;lt;/tex&amp;gt;. Отсюда получаем, что &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt; для любого ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; из остаточной сети &amp;lt;tex&amp;gt;E_{f}&amp;lt;/tex&amp;gt;, что означает, что &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;(-\mu^{*})&amp;lt;/tex&amp;gt;-оптимальный, и, по определению &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\varepsilon^{*} \leqslant -\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Отмена цикла минимального среднего веса не увеличивает &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальности: &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]], &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt;. Но поскольку &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; {{---}} средний вес цикла, то &amp;lt;tex&amp;gt;p_{\varphi}(uv) = \mu^{*} = -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, в остаточной сети появятся ребра стоимости &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Таким образом, свойство &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt; все еще выполняется.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Допустимым графом''' (англ. ''admissible graph'') будем называть такой подграф остаточной сети, что он включает только ребра отрицательной приведенной стоимости. &amp;lt;tex&amp;gt;H=\{uv \in E_{f}\;|\; p_{\varphi}(uv) &amp;lt; 0\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} некоторый поток, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} поток после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен циклов минимального среднего веса. Тогда &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; {{---}} минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
|proof=&lt;br /&gt;
:Изначально любое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. Отмена цикла добавляет в остаточную сеть &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt; только ребра положительной приведенной стоимости (см. [[#lemma4|лемму &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]) и удаляет из сети &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; как минимум одно ребро. Рассмотрим два случая:&lt;br /&gt;
:#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; и после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен граф &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; пуст, что означает, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} оптимальный поток, то есть &amp;lt;tex&amp;gt;\varepsilon'^{*}=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой итерации, и, соответственно, &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; {{---}} первый из таких циклов. Для &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; имеем, что каждое его ребро обладает приведенной стоимостью как минимум &amp;lt;tex&amp;gt;-\varepsilon_{i}^{*}&amp;lt;/tex&amp;gt; (при этом &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}&amp;lt;/tex&amp;gt; по [[#lemma4|лемме &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]), хотя бы одно из ребер &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; обладает неотрицательной приведенной стоимостью и количество ребер в &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; не превышает &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;. Тогда средний вес этого цикла &amp;lt;tex&amp;gt;\mu(C_{i}) = \mu_{i}^{*} \geqslant -\left(1-\dfrac{1}{V}\right)\varepsilon_{i}^{*} \geqslant - \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} = -\mu_{i}^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксированным''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-fixed'') будем называть ребро, поток через которое неизменен для любых &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальных потоков в сети.}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=theorem1&lt;br /&gt;
|statement=Пусть поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальным с функцией потенциалов &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;. Также пусть для некоторого ребра &amp;lt;tex&amp;gt;uv \; \left|p_{\varphi}(uv)\right| \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;. Тогда ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксировано.&lt;br /&gt;
|proof=&lt;br /&gt;
:По свойству антисимметричности, достаточно будет доказать теорему для случая &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим такой поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon &amp;gt; \varepsilon&amp;lt;/tex&amp;gt;, поток по ребру &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; должен быть как можно меньше, то есть &amp;lt;tex&amp;gt;f(uv) = -c(uv)&amp;lt;/tex&amp;gt;, и тогда раз &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f'(uv) &amp;gt; f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Покажем теперь, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
:Обозначим за &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; подграф &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; такой, что &amp;lt;tex&amp;gt;G_{&amp;gt;}=(V, \{uv \in E \;|\; f'(uv) &amp;gt; f(uv) \})&amp;lt;/tex&amp;gt;. Рассмотрим некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; являются циркуляциями, в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; должен содержаться простой цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, проходящий через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Поскольку все ребра в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} остаточные, стоимость &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon &amp;gt; V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Теперь рассмотрим цикл &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt;, который получен из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; разворотом всех его ребер. Заметим, что &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; является циклом в &amp;lt;tex&amp;gt;G_{&amp;lt;}=(V,\{uv \in E \;|\; f'(uv) &amp;lt; f(uv)\})&amp;lt;/tex&amp;gt; и, соответственно, циклом в &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. По свойству антисимметричности, стоимость &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; меньше, чем &amp;lt;tex&amp;gt;-V\varepsilon&amp;lt;/tex&amp;gt; и, таким образом, &amp;lt;tex&amp;gt;\mu(\overline{C}) &amp;lt; -\varepsilon&amp;lt;/tex&amp;gt;. Откуда по [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]] имеем, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимален.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=доказательство оценки времени работы алгоритма в случае вещественных стоимостей&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;k=VE(\lceil \log V + 1 \rceil)&amp;lt;/tex&amp;gt;. Разобьем работу алгоритма на группы по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; последовательных итераций. Утверждается, что каждая группа фиксирует поток на независимом ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, то есть итерации из другой группы не меняют величину &amp;lt;tex&amp;gt;f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Оценка времени работы следует непосредственно из этого утверждения. &lt;br /&gt;
:Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток до первой итерации, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} после последней итерации этой группы. Обозначим за &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, а за &amp;lt;tex&amp;gt;\varphi'&amp;lt;/tex&amp;gt; {{---}} функцию потенциалов такую, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt;-оптимальности. Выбор &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и [[#lemma5|лемма &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;]] дают нам следующее неравенство: &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon^{*} \left(1-\dfrac{1}{V} \right)^{V(\log V + 1)} \leqslant \dfrac{\varepsilon^{*}}{2V}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Рассмотрим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;-\varepsilon^{*}&amp;lt;/tex&amp;gt; (см. [[#lemma3|лемму &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]]), некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; должно иметь приведенную стоимость &amp;lt;tex&amp;gt;p_{\varphi'}(uv) \leqslant -\varepsilon^{*} \leqslant -2V\varepsilon'^{*}&amp;lt;/tex&amp;gt;. Таким образом, поток на ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; не изменится при итерациях, происходящих после этой группы. Таким образом, по [[#theorem1|теореме]] каждая группа фиксирует поток на независимом ребре.}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм поиска цикла минимального среднего веса==&lt;br /&gt;
===Наивный способ===&lt;br /&gt;
Устроим [[Вещественный двоичный поиск |двоичный поиск]].&lt;br /&gt;
Установим нижнюю и верхнюю границы величины среднего веса цикла &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; соответственно, вычислим серединное значение &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; и отнимем полученную величину &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; от всех ребер сети. Если теперь в нашей сети есть отрицательный цикл (этот факт можно проверить при помощи [[Алгоритм Форда-Беллмана #Нахождение отрицательного цикла|алгоритма Форда-Беллмана]]), значит существует цикл с меньшим средним весом, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Тогда продолжим поиск среди значений в диапазоне от &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, иначе {{---}} от &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда, если &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C_{min}&amp;lt;/tex&amp;gt; {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за &amp;lt;tex&amp;gt;O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; {{---}} точность выбора среднего веса цикла.&lt;br /&gt;
При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить &amp;lt;tex&amp;gt;\dfrac{1}{V}&amp;lt;/tex&amp;gt;, что дает нам оценку &amp;lt;tex&amp;gt;O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
    '''func''' findMinCycleBinarySearch (l, r):&lt;br /&gt;
      m = (l + r) / &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' e : edges&lt;br /&gt;
        e.weight -= m&lt;br /&gt;
      '''if''' &amp;lt;tex&amp;gt;\exists C&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu (C) &amp;lt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findMinCycleBinarySearch (l, m)&lt;br /&gt;
      '''else'''&lt;br /&gt;
        findMinCycleBinarySearch (m, r)&lt;br /&gt;
&lt;br /&gt;
===Продвинутый алгоритм===&lt;br /&gt;
Добавим к нашему графу вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и ребра из нее во все остальные вершины.&lt;br /&gt;
Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: &amp;lt;tex&amp;gt;d[i][u]&amp;lt;/tex&amp;gt; {{---}} длина минимального пути от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; ровно из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
Тогда длина оптимального цикла &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимального среднего веса вычисляется как &amp;lt;tex&amp;gt;\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достаточно будет доказать это правило для &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;, так как для других &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; можно просто отнять эту величину от всех ребер и получить снова случай с &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы найти цикл после построения матрицы &amp;lt;tex&amp;gt;d[k][u]&amp;lt;/tex&amp;gt;, запомним, при каких &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; достигается оптимальное значение &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt;, и, используя &amp;lt;tex&amp;gt;d[n][u]&amp;lt;/tex&amp;gt;, поднимемся по указателям предков. Как только мы попадем в уже посещенную вершину {{---}} мы нашли цикл минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм работает за &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; &amp;lt;ref&amp;gt;[[Алгоритм Форда-Беллмана #Сложность| Сложность алгоритма Форда-Беллмана]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  '''func''' findMinCycle:&lt;br /&gt;
    '''Node''' s&lt;br /&gt;
    '''Edge''' e&lt;br /&gt;
    insert(s)                                         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// добавляем мнимую вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и проводим рёбра нулевого веса в каждую вершину графа&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' u '''in''' &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
      e.begin = s&lt;br /&gt;
      e.end = u&lt;br /&gt;
      e.weight = &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    fordBellman(s)&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mu^{*} = \min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&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;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://youtu.be/bykbw7HovSo?t=4287 Лекция 14 | Дополнительные главы алгоритмов | Андрей Станкевич | CSC | Лекториум]&lt;br /&gt;
* [http://sirius.cs.put.poznan.pl/~inf84789/acm/p873-goldberg.pdf A.V.Goldberg and R.E.Tarjan {{---}} Finding Minimum-Cost Circulations by Cancelling Negative Cycles (Journal of the Association for Computing Machinery. Vol. 36, No. 4. October 1989. pp. 873-886.)]&lt;br /&gt;
*[https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-854j-advanced-algorithms-fall-2008/lecture-notes/lec4.pdf Lecture by M.X.Goemans on Goldberg-Tarjan Min-Cost Circulation Algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64686</id>
		<title>Алгоритм отмены цикла минимального среднего веса</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64686"/>
				<updated>2018-03-30T04:24:05Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В статье описывается один из сильно полиномиальных алгоритмов решения [[Поток минимальной стоимости #Задача о потоке минимальной стоимости|задачи о поиске потока минимальной стоимости]].&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
Приведенный алгоритм основан на идее [[Поток минимальной стоимости #Метод устранения отрицательных циклов в остаточной сети|алгоритма Клейна отмены цикла отрицательного веса]]. Выбор цикла минимального среднего веса вместо случайного делает алгоритм сильно полиномиальным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Сильно полиномиальными''' (англ. ''strongly polynomial'') в контексте данной задачи называются алгоритмы, чья сложность полиномиально зависит от &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
===Описание===&lt;br /&gt;
Обозначим как &amp;lt;tex&amp;gt;c_{f}(C)&amp;lt;/tex&amp;gt; остаточную [[Определение сети, потока|пропускную способность]] цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; при протекании в сети потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Cтоимость цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; обозначим за &amp;lt;tex&amp;gt;p(C)&amp;lt;/tex&amp;gt;, а длину (число входящих в него ребер) {{---}} за &amp;lt;tex&amp;gt;\texttt{len}(C)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Средним весом''' (англ. ''mean weight'') цикла будем называть отношение его стоимости к его длине &amp;lt;tex&amp;gt;\mu (C)=\dfrac{p(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;}}&lt;br /&gt;
Данный алгоритм заключается в последовательной отмене циклов минимального среднего веса в [[Дополняющая сеть, дополняющий путь|остаточной сети]] посредством их насыщения. Алгоритм работает до тех пор, пока минимальный средний вес циклов не окажется положительным, что будет означать, что поток минимальной стоимости найден. &lt;br /&gt;
&lt;br /&gt;
Более формально:&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''. Рассмотрим некоторый поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;'''. Найдем цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, обладающий наименьшим средним весом. Если &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости и алгоритм завершается.&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;'''. Отменим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, пустив по нему максимально возможный поток: &amp;lt;tex&amp;gt;f = f + c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;. Перейдем к '''шагу &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
===Сложность===&lt;br /&gt;
Для сетей с целочисленными стоимостями на ребрах &amp;lt;tex&amp;gt;O(VE\cdot VE\log{CV})&amp;lt;/tex&amp;gt;, с вещественными {{---}} &amp;lt;tex&amp;gt;O(VE\cdot VE^{2}\log{V})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В обоих случаях &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; времени тратится на поиск цикла минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
  '''func''' findMin:&lt;br /&gt;
  '''while''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu(C) =\mathrm{min}\limits_c \mu(c)&amp;lt;/tex&amp;gt;            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// &amp;lt;tex&amp;gt;\mu(C)&amp;lt;/tex&amp;gt; {{---}} вес минимального цикла&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// тогда мы нашли f {{---}} поток минимальной стоимости, алгоритм завершается&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''else'''&lt;br /&gt;
      &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; += &amp;lt;tex&amp;gt;c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// иначе отменим цикл&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости. Введём на нашей сети функцию [[Алгоритм Джонсона|потенциалов]] &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Приведённой стоимостью''' (англ. ''reduced cost'') ребра назовем следующую величину: &amp;lt;tex&amp;gt;p_{\varphi}(uv)=\varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
Иными словами, приведённая стоимость {{---}} это сколько нужно потратить денег, чтобы перевезти единицу жидкости из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; (её нужно купить в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, перевезти из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и продать в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости, то &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;\forall uv: \; c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Рассмотрим остаточную сеть {{---}} граф &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В нем нет отрицательных циклов, так как &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости&amp;lt;ref&amp;gt;[[Лемма об эквивалентности свойства потока быть минимальной стоимости и отсутствии отрицательных циклов в остаточной сети]]&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим теперь некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Понятно, что &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p(uv)&amp;lt;/tex&amp;gt;. (Здесь сравниваются минимальный путь &amp;lt;tex&amp;gt;a \rightsquigarrow v&amp;lt;/tex&amp;gt; и путь &amp;lt;tex&amp;gt;a \rightsquigarrow u \rightarrow v&amp;lt;/tex&amp;gt;). Перенеся &amp;lt;tex&amp;gt;\varphi(v)&amp;lt;/tex&amp;gt; в другую часть неравенства, получаем &amp;lt;tex&amp;gt;0 \leqslant \varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;0 \leqslant p_{\varphi}(uv)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Будем говорить, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} '''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-optimal''), если &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt;\forall uv: c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если стоимости целочисленны и поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, где &amp;lt;tex&amp;gt;\varepsilon &amp;lt; \dfrac{1}{V}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.&lt;br /&gt;
|proof= &lt;br /&gt;
:Рассмотрим цикл в остаточной сети &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;p(C)=p_{\varphi}(C)&amp;lt;/tex&amp;gt; (для доказательства этого факта достаточно расписать &amp;lt;tex&amp;gt;p_{\varphi}(C)&amp;lt;/tex&amp;gt; по определению).&lt;br /&gt;
&lt;br /&gt;
:Возьмем &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; такое, что стоимости всех ребер в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;-\varepsilon&amp;lt;/tex&amp;gt;. Тогда стоимость всего цикла &amp;lt;tex&amp;gt;p_{\varphi}(C)\geqslant -V\cdot \varepsilon&amp;lt;/tex&amp;gt; (в цикле не больше &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; ребер). Таким образом, &amp;lt;tex&amp;gt;p_{\varphi}(C) &amp;gt; -1&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p(C) &amp;gt; -1&amp;lt;/tex&amp;gt;. Но исходные пропускные способности были целочисленными, поэтому &amp;lt;tex&amp;gt;p(C) \geqslant 0&amp;lt;/tex&amp;gt;, а это означает, что в остаточной сети нет отрицательных циклов, и, соответственно, &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.}}&lt;br /&gt;
&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимальную величину среди средних весов циклов для потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, а за &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток не минимальной стоимости, то &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса в остаточной сети.&lt;br /&gt;
*Покажем, что &amp;lt;tex&amp;gt;\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Поскольку поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальным, верно следующее: &amp;lt;tex&amp;gt;p(C) = p_{\varphi}(C) \geqslant -\texttt{len}(C) \cdot \varepsilon^{*}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\dfrac{p(C)}{\texttt{len}(C)} \geqslant -\varepsilon^{*} &amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;\mu(C)=\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Теперь покажем, что &amp;lt;tex&amp;gt;\mu^{*} \leqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;p'(uv)=p(uv)-\mu^{*}&amp;lt;/tex&amp;gt; для любого &amp;lt;tex&amp;gt;uv \in E_{f}&amp;lt;/tex&amp;gt;. Логичным будет также обозначить для некоторого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;\mu'(C)&amp;lt;/tex&amp;gt; величину &amp;lt;tex&amp;gt;\dfrac{p'(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;. Таким образом, для любого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mu'(C)=\mu(C)-\mu^{*}\geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость (считая стоимостью функцию &amp;lt;tex&amp;gt;p'&amp;lt;/tex&amp;gt;) минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Таким образом, &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}&amp;lt;/tex&amp;gt;. Отсюда получаем, что &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt; для любого ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; из остаточной сети &amp;lt;tex&amp;gt;E_{f}&amp;lt;/tex&amp;gt;, что означает, что &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;(-\mu^{*})&amp;lt;/tex&amp;gt;-оптимальный, и, по определению &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\varepsilon^{*} \leqslant -\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Отмена цикла минимального среднего веса не увеличивает &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальности: &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]], &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt;. Но поскольку &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; {{---}} средний вес цикла, то &amp;lt;tex&amp;gt;p_{\varphi}(uv) = \mu^{*} = -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, в остаточной сети появятся ребра стоимости &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Таким образом, свойство &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt; все еще выполняется.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Допустимым графом''' (англ. ''admissible graph'') будем называть такой подграф остаточной сети, что он включает только ребра отрицательной приведенной стоимости. &amp;lt;tex&amp;gt;H=\{uv \in E_{f}\;|\; p_{\varphi}(uv) &amp;lt; 0\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} некоторый поток, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} поток после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен циклов минимального среднего веса. Тогда &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; {{---}} минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
|proof=&lt;br /&gt;
:Изначально любое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. Отмена цикла добавляет в остаточную сеть &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt; только ребра положительной приведенной стоимости (см. [[#lemma4|лемму &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]) и удаляет из сети &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; как минимум одно ребро. Рассмотрим два случая:&lt;br /&gt;
:#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; и после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен граф &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; пуст, что означает, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} оптимальный поток, то есть &amp;lt;tex&amp;gt;\varepsilon'^{*}=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой итерации, и, соответственно, &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; {{---}} первый из таких циклов. Для &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; имеем, что каждое его ребро обладает приведенной стоимостью как минимум &amp;lt;tex&amp;gt;-\varepsilon_{i}^{*}&amp;lt;/tex&amp;gt; (при этом &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}&amp;lt;/tex&amp;gt; по [[#lemma4|лемме &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]), хотя бы одно из ребер &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; обладает неотрицательной приведенной стоимостью и количество ребер в &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; не превышает &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;. Тогда средний вес этого цикла &amp;lt;tex&amp;gt;\mu(C_{i}) = \mu_{i}^{*} \geqslant -\left(1-\dfrac{1}{V}\right)\varepsilon_{i}^{*} \geqslant - \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} = -\mu_{i}^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксированным''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-fixed'') будем называть ребро, поток через которое неизменен для любых &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальных потоков в сети.}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=theorem1&lt;br /&gt;
|statement=Пусть поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальным с функцией потенциалов &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;. Также пусть для некоторого ребра &amp;lt;tex&amp;gt;uv \; \left|p_{\varphi}(uv)\right| \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;. Тогда ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксировано.&lt;br /&gt;
|proof=&lt;br /&gt;
:По свойству антисимметричности, достаточно будет доказать теорему для случая &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим такой поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon &amp;gt; \varepsilon&amp;lt;/tex&amp;gt;, поток по ребру &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; должен быть как можно меньше, то есть &amp;lt;tex&amp;gt;f(uv) = -c(uv)&amp;lt;/tex&amp;gt;, и тогда раз &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f'(uv) &amp;gt; f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Покажем теперь, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
:Обозначим за &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; подграф &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; такой, что &amp;lt;tex&amp;gt;G_{&amp;gt;}=(V, \{uv \in E \;|\; f'(uv) &amp;gt; f(uv) \})&amp;lt;/tex&amp;gt;. Рассмотрим некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; являются циркуляциями, в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; должен содержаться простой цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, проходящий через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Поскольку все ребра в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} остаточные, стоимость &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon &amp;gt; V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Теперь рассмотрим цикл &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt;, который получен из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; разворотом всех его ребер. Заметим, что &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; является циклом в &amp;lt;tex&amp;gt;G_{&amp;lt;}=(V,\{uv \in E \;|\; f'(uv) &amp;lt; f(uv)\})&amp;lt;/tex&amp;gt; и, соответственно, циклом в &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. По свойству антисимметричности, стоимость &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; меньше, чем &amp;lt;tex&amp;gt;-V\varepsilon&amp;lt;/tex&amp;gt; и, таким образом, &amp;lt;tex&amp;gt;\mu(\overline{C}) &amp;lt; -\varepsilon&amp;lt;/tex&amp;gt;. Откуда по [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]] имеем, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимален.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=доказательство оценки времени работы алгоритма в случае вещественных стоимостей&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;k=VE(\lceil \log V + 1 \rceil)&amp;lt;/tex&amp;gt;. Разобьем работу алгоритма на группы по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; последовательных итераций. Утверждается, что каждая группа фиксирует поток на независимом ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, то есть итерации из другой группы не меняют величину &amp;lt;tex&amp;gt;f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Оценка времени работы следует непосредственно из этого утверждения. &lt;br /&gt;
:Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток до первой итерации, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} после последней итерации этой группы. Обозначим за &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, а за &amp;lt;tex&amp;gt;\varphi'&amp;lt;/tex&amp;gt; {{---}} функцию потенциалов такую, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt;-оптимальности. Выбор &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и [[#lemma5|лемма &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;]] дают нам следующее неравенство: &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon^{*} \left(1-\dfrac{1}{V} \right)^{V(\log V + 1)} \leqslant \dfrac{\varepsilon^{*}}{2V}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Рассмотрим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;-\varepsilon^{*}&amp;lt;/tex&amp;gt; (см. [[#lemma3|лемму &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]]), некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; должно иметь приведенную стоимость &amp;lt;tex&amp;gt;p_{\varphi'}(uv) \leqslant -\varepsilon^{*} \leqslant -2V\varepsilon'^{*}&amp;lt;/tex&amp;gt;. Таким образом, поток на ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; не изменится при итерациях, происходящих после этой группы. Таким образом, по [[#theorem1|теореме]] каждая группа фиксирует поток на независимом ребре.}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм поиска цикла минимального среднего веса==&lt;br /&gt;
===Наивный способ===&lt;br /&gt;
Устроим [[Вещественный двоичный поиск |двоичный поиск]].&lt;br /&gt;
Установим нижнюю и верхнюю границы величины среднего веса цикла &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; соответственно, вычислим серединное значение &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; и отнимем полученную величину &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; от всех ребер сети. Если теперь в нашей сети есть отрицательный цикл (этот факт можно проверить при помощи [[Алгоритм Форда-Беллмана #Нахождение отрицательного цикла|алгоритма Форда-Беллмана]]), значит существует цикл с меньшим средним весом, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Тогда продолжим поиск среди значений в диапазоне от &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, иначе {{---}} от &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда, если &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C_{min}&amp;lt;/tex&amp;gt; {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за &amp;lt;tex&amp;gt;O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; {{---}} точность выбора среднего веса цикла.&lt;br /&gt;
При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить &amp;lt;tex&amp;gt;\dfrac{1}{V}&amp;lt;/tex&amp;gt;, что дает нам оценку &amp;lt;tex&amp;gt;O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
    '''func''' findMinCycleBinarySearch (l, r):&lt;br /&gt;
      m = (l + r) / &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' e : edges&lt;br /&gt;
        e.weight -= m&lt;br /&gt;
      '''if''' &amp;lt;tex&amp;gt;\exists C&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu (C) &amp;lt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findMinCycleBinarySearch (l, m)&lt;br /&gt;
      '''else'''&lt;br /&gt;
        findMinCycleBinarySearch (m, r)&lt;br /&gt;
&lt;br /&gt;
===Продвинутый алгоритм===&lt;br /&gt;
Добавим к нашему графу вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и ребра из нее во все остальные вершины.&lt;br /&gt;
Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: &amp;lt;tex&amp;gt;d[i][u]&amp;lt;/tex&amp;gt; {{---}} длина минимального пути от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; ровно из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
Тогда длина оптимального цикла &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимального среднего веса вычисляется как &amp;lt;tex&amp;gt;\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достаточно будет доказать это правило для &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;, так как для других &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; можно просто отнять эту величину от всех ребер и получить снова случай с &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы найти цикл после построения матрицы &amp;lt;tex&amp;gt;d[k][u]&amp;lt;/tex&amp;gt;, запомним, при каких &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; достигается оптимальное значение &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt;, и, используя &amp;lt;tex&amp;gt;d[n][u]&amp;lt;/tex&amp;gt;, поднимемся по указателям предков. Как только мы попадем в уже посещенную вершину {{---}} мы нашли цикл минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм работает за &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; &amp;lt;ref&amp;gt;[[Алгоритм Форда-Беллмана #Сложность| Сложность алгоритма Форда-Беллмана]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  '''func''' findMinCycle:&lt;br /&gt;
    '''Node''' s&lt;br /&gt;
    '''Edge''' e&lt;br /&gt;
    insert(s)                                         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// добавляем мнимую вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и проводим рёбра нулевого веса в каждую вершину графа&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' u '''in''' &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
      e.begin = s&lt;br /&gt;
      e.end = u&lt;br /&gt;
      e.weight = &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    fordBellman(s)&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mu^{*} = \min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&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;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://youtu.be/bykbw7HovSo?t=4287 Лекция 14 | Дополнительные главы алгоритмов | Андрей Станкевич | CSC | Лекториум]&lt;br /&gt;
* [http://sirius.cs.put.poznan.pl/~inf84789/acm/p873-goldberg.pdf A.V.Goldberg and R.E.Tarjan {{---}} Finding Minimum-Cost Circulations by Cancelling Negative Cycles (Journal of the Association for Computing Machinery. Vol. 36, No. 4. October 1989. pp. 873-886.)]&lt;br /&gt;
*[https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-854j-advanced-algorithms-fall-2008/lecture-notes/lec4.pdf Lecture by M.X.Goemans on Goldberg-Tarjan Min-Cost Circulation Algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64685</id>
		<title>Алгоритм отмены цикла минимального среднего веса</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D1%8B_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B2%D0%B5%D1%81%D0%B0&amp;diff=64685"/>
				<updated>2018-03-30T04:18:01Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В статье описывается один из сильно полиномиальных алгоритмов решения [[Поток минимальной стоимости #Задача о потоке минимальной стоимости|задачи о поиске потока минимальной стоимости]].&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
Приведенный алгоритм основан на идее [[Поток минимальной стоимости #Метод устранения отрицательных циклов в остаточной сети|алгоритма Клейна отмены цикла отрицательного веса]]. Выбор цикла минимального среднего веса вместо случайного делает алгоритм сильно полиномиальным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Сильно полиномиальными''' (англ. ''strongly polynomial'') в контексте данной задачи называются алгоритмы, чья сложность полиномиально зависит от &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
===Описание===&lt;br /&gt;
Обозначим как &amp;lt;tex&amp;gt;c_{f}(C)&amp;lt;/tex&amp;gt; остаточную [[Определение сети, потока|пропускную способность]] цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; при протекании в сети потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Cтоимость цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; обозначим за &amp;lt;tex&amp;gt;p(C)&amp;lt;/tex&amp;gt;, а длину (число входящих в него ребер) {{---}} за &amp;lt;tex&amp;gt;\texttt{len}(C)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Средним весом''' (англ. ''mean weight'') цикла будем называть отношение его стоимости к его длине &amp;lt;tex&amp;gt;\mu (C)=\dfrac{p(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;}}&lt;br /&gt;
Данный алгоритм заключается в последовательной отмене циклов минимального среднего веса в [[Дополняющая сеть, дополняющий путь|остаточной сети]] посредством их насыщения. Алгоритм работает до тех пор, пока минимальный средний вес циклов не окажется положительным, что будет означать, что поток минимальной стоимости найден. &lt;br /&gt;
&lt;br /&gt;
Более формально:&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''. Рассмотрим некоторый поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;'''. Найдем цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, обладающий наименьшим средним весом. Если &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости и алгоритм завершается.&lt;br /&gt;
* '''Шаг &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;'''. Отменим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, пустив по нему максимально возможный поток: &amp;lt;tex&amp;gt;f = f + c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;. Перейдем к '''шагу &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
===Сложность===&lt;br /&gt;
Для сетей с целочисленными стоимостями на ребрах &amp;lt;tex&amp;gt;O(VE\cdot VE\log{CV})&amp;lt;/tex&amp;gt;, с вещественными {{---}} &amp;lt;tex&amp;gt;O(VE\cdot VE^{2}\log{V})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В обоих случаях &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; времени тратится на поиск цикла минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
  '''func''' findMin:&lt;br /&gt;
  '''while''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\mathrm{min} \mu(C)&amp;lt;!-----лажа какая-то...------&amp;gt;&amp;lt;/tex&amp;gt;            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// &amp;lt;tex&amp;gt;\mu(C)&amp;lt;/tex&amp;gt; {{---}} вес минимального цикла&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;\mu (C) \geqslant 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// тогда мы нашли f {{---}} поток минимальной стоимости, алгоритм завершается&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''else'''&lt;br /&gt;
      &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; += &amp;lt;tex&amp;gt;c_{f}(C)\cdot f_{C}&amp;lt;/tex&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// иначе отменим цикл&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости. Введём на нашей сети функцию [[Алгоритм Джонсона|потенциалов]] &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Приведённой стоимостью''' (англ. ''reduced cost'') ребра назовем следующую величину: &amp;lt;tex&amp;gt;p_{\varphi}(uv)=\varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
Иными словами, приведённая стоимость {{---}} это сколько нужно потратить денег, чтобы перевезти единицу жидкости из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; (её нужно купить в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, перевезти из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и продать в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости, то &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;\forall uv: \; c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Рассмотрим остаточную сеть {{---}} граф &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В нем нет отрицательных циклов, так как &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости&amp;lt;ref&amp;gt;[[Лемма об эквивалентности свойства потока быть минимальной стоимости и отсутствии отрицательных циклов в остаточной сети]]&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим теперь некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Понятно, что &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p(uv)&amp;lt;/tex&amp;gt;. (Здесь сравниваются минимальный путь &amp;lt;tex&amp;gt;a \rightsquigarrow v&amp;lt;/tex&amp;gt; и путь &amp;lt;tex&amp;gt;a \rightsquigarrow u \rightarrow v&amp;lt;/tex&amp;gt;). Перенеся &amp;lt;tex&amp;gt;\varphi(v)&amp;lt;/tex&amp;gt; в другую часть неравенства, получаем &amp;lt;tex&amp;gt;0 \leqslant \varphi(u) + p(uv) - \varphi(v)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;0 \leqslant p_{\varphi}(uv)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Будем говорить, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} '''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-optimal''), если &amp;lt;tex&amp;gt;\exists \varphi&amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt;\forall uv: c_{f}(uv) &amp;gt; 0 \implies p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если стоимости целочисленны и поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, где &amp;lt;tex&amp;gt;\varepsilon &amp;lt; \dfrac{1}{V}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.&lt;br /&gt;
|proof= &lt;br /&gt;
:Рассмотрим цикл в остаточной сети &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;p(C)=p_{\varphi}(C)&amp;lt;/tex&amp;gt; (для доказательства этого факта достаточно расписать &amp;lt;tex&amp;gt;p_{\varphi}(C)&amp;lt;/tex&amp;gt; по определению).&lt;br /&gt;
&lt;br /&gt;
:Возьмем &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; такое, что стоимости всех ребер в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;-\varepsilon&amp;lt;/tex&amp;gt;. Тогда стоимость всего цикла &amp;lt;tex&amp;gt;p_{\varphi}(C)\geqslant -V\cdot \varepsilon&amp;lt;/tex&amp;gt; (в цикле не больше &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; ребер). Таким образом, &amp;lt;tex&amp;gt;p_{\varphi}(C) &amp;gt; -1&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p(C) &amp;gt; -1&amp;lt;/tex&amp;gt;. Но исходные пропускные способности были целочисленными, поэтому &amp;lt;tex&amp;gt;p(C) \geqslant 0&amp;lt;/tex&amp;gt;, а это означает, что в остаточной сети нет отрицательных циклов, и, соответственно, &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток минимальной стоимости.}}&lt;br /&gt;
&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимальную величину среди средних весов циклов для потока &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, а за &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток не минимальной стоимости, то &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса в остаточной сети.&lt;br /&gt;
*Покажем, что &amp;lt;tex&amp;gt;\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Поскольку поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальным, верно следующее: &amp;lt;tex&amp;gt;p(C) = p_{\varphi}(C) \geqslant -\texttt{len}(C) \cdot \varepsilon^{*}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\dfrac{p(C)}{\texttt{len}(C)} \geqslant -\varepsilon^{*} &amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;\mu(C)=\mu^{*} \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Теперь покажем, что &amp;lt;tex&amp;gt;\mu^{*} \leqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;p'(uv)=p(uv)-\mu^{*}&amp;lt;/tex&amp;gt; для любого &amp;lt;tex&amp;gt;uv \in E_{f}&amp;lt;/tex&amp;gt;. Логичным будет также обозначить для некоторого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;\mu'(C)&amp;lt;/tex&amp;gt; величину &amp;lt;tex&amp;gt;\dfrac{p'(C)}{\texttt{len}(C)}&amp;lt;/tex&amp;gt;. Таким образом, для любого цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mu'(C)=\mu(C)-\mu^{*}\geqslant 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
:Добавим вершину &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и проведем из нее ребро стоимости &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во все вершины графа &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. В качестве &amp;lt;tex&amp;gt;\varphi(u)&amp;lt;/tex&amp;gt; выберем стоимость (считая стоимостью функцию &amp;lt;tex&amp;gt;p'&amp;lt;/tex&amp;gt;) минимального пути из &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Таким образом, &amp;lt;tex&amp;gt;\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}&amp;lt;/tex&amp;gt;. Отсюда получаем, что &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt; для любого ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; из остаточной сети &amp;lt;tex&amp;gt;E_{f}&amp;lt;/tex&amp;gt;, что означает, что &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;(-\mu^{*})&amp;lt;/tex&amp;gt;-оптимальный, и, по определению &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\varepsilon^{*} \leqslant -\mu^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Отмена цикла минимального среднего веса не увеличивает &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon^{*}&amp;lt;/tex&amp;gt;-оптимальности: &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]], &amp;lt;tex&amp;gt;\varepsilon^{*}=-\mu^{*}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant \mu^{*}&amp;lt;/tex&amp;gt;. Но поскольку &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; {{---}} средний вес цикла, то &amp;lt;tex&amp;gt;p_{\varphi}(uv) = \mu^{*} = -\varepsilon^{*}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, в остаточной сети появятся ребра стоимости &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Таким образом, свойство &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon&amp;lt;/tex&amp;gt; все еще выполняется.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Допустимым графом''' (англ. ''admissible graph'') будем называть такой подграф остаточной сети, что он включает только ребра отрицательной приведенной стоимости. &amp;lt;tex&amp;gt;H=\{uv \in E_{f}\;|\; p_{\varphi}(uv) &amp;lt; 0\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=&amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} некоторый поток, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} поток после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен циклов минимального среднего веса. Тогда &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; {{---}} минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
|proof=&lt;br /&gt;
:Изначально любое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant -\varepsilon^{*}&amp;lt;/tex&amp;gt;. Отмена цикла добавляет в остаточную сеть &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt; только ребра положительной приведенной стоимости (см. [[#lemma4|лемму &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]) и удаляет из сети &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; как минимум одно ребро. Рассмотрим два случая:&lt;br /&gt;
:#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; и после &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; отмен граф &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; пуст, что означает, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} оптимальный поток, то есть &amp;lt;tex&amp;gt;\varepsilon'^{*}=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой итерации, и, соответственно, &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; {{---}} первый из таких циклов. Для &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; имеем, что каждое его ребро обладает приведенной стоимостью как минимум &amp;lt;tex&amp;gt;-\varepsilon_{i}^{*}&amp;lt;/tex&amp;gt; (при этом &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}&amp;lt;/tex&amp;gt; по [[#lemma4|лемме &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;]]), хотя бы одно из ребер &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; обладает неотрицательной приведенной стоимостью и количество ребер в &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt; не превышает &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;. Тогда средний вес этого цикла &amp;lt;tex&amp;gt;\mu(C_{i}) = \mu_{i}^{*} \geqslant -\left(1-\dfrac{1}{V}\right)\varepsilon_{i}^{*} \geqslant - \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} = -\mu_{i}^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксированным''' (англ. ''&amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-fixed'') будем называть ребро, поток через которое неизменен для любых &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальных потоков в сети.}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=theorem1&lt;br /&gt;
|statement=Пусть поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальным с функцией потенциалов &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;. Также пусть для некоторого ребра &amp;lt;tex&amp;gt;uv \; \left|p_{\varphi}(uv)\right| \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;. Тогда ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-фиксировано.&lt;br /&gt;
|proof=&lt;br /&gt;
:По свойству антисимметричности, достаточно будет доказать теорему для случая &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим такой поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;p_{\varphi}(uv) \geqslant 2V\varepsilon &amp;gt; \varepsilon&amp;lt;/tex&amp;gt;, поток по ребру &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; должен быть как можно меньше, то есть &amp;lt;tex&amp;gt;f(uv) = -c(uv)&amp;lt;/tex&amp;gt;, и тогда раз &amp;lt;tex&amp;gt;f'(uv) \neq f(uv)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f'(uv) &amp;gt; f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Покажем теперь, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный.&lt;br /&gt;
:Обозначим за &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; подграф &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; такой, что &amp;lt;tex&amp;gt;G_{&amp;gt;}=(V, \{uv \in E \;|\; f'(uv) &amp;gt; f(uv) \})&amp;lt;/tex&amp;gt;. Рассмотрим некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt;. Поскольку &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; являются циркуляциями, в &amp;lt;tex&amp;gt;G_{&amp;gt;}&amp;lt;/tex&amp;gt; должен содержаться простой цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, проходящий через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Поскольку все ребра в &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} остаточные, стоимость &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; не меньше &amp;lt;tex&amp;gt;p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon &amp;gt; V\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Теперь рассмотрим цикл &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt;, который получен из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; разворотом всех его ребер. Заметим, что &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; является циклом в &amp;lt;tex&amp;gt;G_{&amp;lt;}=(V,\{uv \in E \;|\; f'(uv) &amp;lt; f(uv)\})&amp;lt;/tex&amp;gt; и, соответственно, циклом в &amp;lt;tex&amp;gt;G_{f}&amp;lt;/tex&amp;gt;. По свойству антисимметричности, стоимость &amp;lt;tex&amp;gt;\overline{C}&amp;lt;/tex&amp;gt; меньше, чем &amp;lt;tex&amp;gt;-V\varepsilon&amp;lt;/tex&amp;gt; и, таким образом, &amp;lt;tex&amp;gt;\mu(\overline{C}) &amp;lt; -\varepsilon&amp;lt;/tex&amp;gt;. Откуда по [[#lemma3|лемме &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]] имеем, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; не &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимален.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=доказательство оценки времени работы алгоритма в случае вещественных стоимостей&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;k=VE(\lceil \log V + 1 \rceil)&amp;lt;/tex&amp;gt;. Разобьем работу алгоритма на группы по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; последовательных итераций. Утверждается, что каждая группа фиксирует поток на независимом ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, то есть итерации из другой группы не меняют величину &amp;lt;tex&amp;gt;f(uv)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
:Оценка времени работы следует непосредственно из этого утверждения. &lt;br /&gt;
:Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; {{---}} поток до первой итерации, а &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; {{---}} после последней итерации этой группы. Обозначим за &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt; минимальное &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; такое, что поток &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-оптимальный, а за &amp;lt;tex&amp;gt;\varphi'&amp;lt;/tex&amp;gt; {{---}} функцию потенциалов такую, что &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt; удовлетворяет свойству &amp;lt;tex&amp;gt;\varepsilon'^{*}&amp;lt;/tex&amp;gt;-оптимальности. Выбор &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и [[#lemma5|лемма &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;]] дают нам следующее неравенство: &amp;lt;tex&amp;gt;\varepsilon'^{*} \leqslant \varepsilon^{*} \left(1-\dfrac{1}{V} \right)^{V(\log V + 1)} \leqslant \dfrac{\varepsilon^{*}}{2V}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Рассмотрим цикл &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;-\varepsilon^{*}&amp;lt;/tex&amp;gt; (см. [[#lemma3|лемму &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;]]), некоторое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; цикла &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; должно иметь приведенную стоимость &amp;lt;tex&amp;gt;p_{\varphi'}(uv) \leqslant -\varepsilon^{*} \leqslant -2V\varepsilon'^{*}&amp;lt;/tex&amp;gt;. Таким образом, поток на ребре &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; не изменится при итерациях, происходящих после этой группы. Таким образом, по [[#theorem1|теореме]] каждая группа фиксирует поток на независимом ребре.}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм поиска цикла минимального среднего веса==&lt;br /&gt;
===Наивный способ===&lt;br /&gt;
Устроим [[Вещественный двоичный поиск |двоичный поиск]].&lt;br /&gt;
Установим нижнюю и верхнюю границы величины среднего веса цикла &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; соответственно, вычислим серединное значение &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; и отнимем полученную величину &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; от всех ребер сети. Если теперь в нашей сети есть отрицательный цикл (этот факт можно проверить при помощи [[Алгоритм Форда-Беллмана #Нахождение отрицательного цикла|алгоритма Форда-Беллмана]]), значит существует цикл с меньшим средним весом, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Тогда продолжим поиск среди значений в диапазоне от &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, иначе {{---}} от &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда, если &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C_{min}&amp;lt;/tex&amp;gt; {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за &amp;lt;tex&amp;gt;O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; {{---}} точность выбора среднего веса цикла.&lt;br /&gt;
При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить &amp;lt;tex&amp;gt;\dfrac{1}{V}&amp;lt;/tex&amp;gt;, что дает нам оценку &amp;lt;tex&amp;gt;O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
    '''func''' findMinCycleBinarySearch (l, r):&lt;br /&gt;
      m = (l + r) / &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' e : edges&lt;br /&gt;
        e.weight -= m&lt;br /&gt;
      '''if''' &amp;lt;tex&amp;gt;\exists C&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;\mu (C) &amp;lt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findMinCycleBinarySearch (l, m)&lt;br /&gt;
      '''else'''&lt;br /&gt;
        findMinCycleBinarySearch (m, r)&lt;br /&gt;
&lt;br /&gt;
===Продвинутый алгоритм===&lt;br /&gt;
Добавим к нашему графу вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и ребра из нее во все остальные вершины.&lt;br /&gt;
Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: &amp;lt;tex&amp;gt;d[i][u]&amp;lt;/tex&amp;gt; {{---}} длина минимального пути от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; ровно из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; ребер.&lt;br /&gt;
Тогда длина оптимального цикла &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; минимального среднего веса вычисляется как &amp;lt;tex&amp;gt;\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достаточно будет доказать это правило для &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;, так как для других &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt; можно просто отнять эту величину от всех ребер и получить снова случай с &amp;lt;tex&amp;gt;\mu^{*}=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы найти цикл после построения матрицы &amp;lt;tex&amp;gt;d[k][u]&amp;lt;/tex&amp;gt;, запомним, при каких &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; достигается оптимальное значение &amp;lt;tex&amp;gt;\mu^{*}&amp;lt;/tex&amp;gt;, и, используя &amp;lt;tex&amp;gt;d[n][u]&amp;lt;/tex&amp;gt;, поднимемся по указателям предков. Как только мы попадем в уже посещенную вершину {{---}} мы нашли цикл минимального среднего веса.&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм работает за &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt; &amp;lt;ref&amp;gt;[[Алгоритм Форда-Беллмана #Сложность| Сложность алгоритма Форда-Беллмана]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  '''func''' findMinCycle:&lt;br /&gt;
    '''Node''' s&lt;br /&gt;
    '''Edge''' e&lt;br /&gt;
    insert(s)                                         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// добавляем мнимую вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и проводим рёбра нулевого веса в каждую вершину графа&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' u '''in''' &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
      e.begin = s&lt;br /&gt;
      e.end = u&lt;br /&gt;
      e.weight = &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    fordBellman(s)&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mu^{*} = \min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}&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;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://youtu.be/bykbw7HovSo?t=4287 Лекция 14 | Дополнительные главы алгоритмов | Андрей Станкевич | CSC | Лекториум]&lt;br /&gt;
* [http://sirius.cs.put.poznan.pl/~inf84789/acm/p873-goldberg.pdf A.V.Goldberg and R.E.Tarjan {{---}} Finding Minimum-Cost Circulations by Cancelling Negative Cycles (Journal of the Association for Computing Machinery. Vol. 36, No. 4. October 1989. pp. 873-886.)]&lt;br /&gt;
*[https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-854j-advanced-algorithms-fall-2008/lecture-notes/lec4.pdf Lecture by M.X.Goemans on Goldberg-Tarjan Min-Cost Circulation Algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о потоке минимальной стоимости]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D0%94%D0%9C_2%D0%BA_2018_%D0%B2%D0%B5%D1%81%D0%BD%D0%B0&amp;diff=64549</id>
		<title>Список заданий по ДМ 2к 2018 весна</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D0%94%D0%9C_2%D0%BA_2018_%D0%B2%D0%B5%D1%81%D0%BD%D0%B0&amp;diff=64549"/>
				<updated>2018-03-22T17:16:22Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: грамм. ошибки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;# Формальный степенной ряд $\exp(s) = e^s$ определен как $e^s=1+\frac{1}{1!}s+\frac{1}{2!}s^2+\frac{1}{3!}s^3+\ldots+\frac{1}{n!}s^n+\ldots$. Логично, что $e^{-s}=1-\frac{1}{1!}s+\frac{1}{2!}s^2-\frac{1}{3!}s^3+\ldots+(-1)^n\frac{1}{n!}s^n+\ldots$. Докажите, используя определение умножения для степенных рядов, что $e^se^{-s}=1$.&lt;br /&gt;
# Формальный степенной ряд $(1+s)^\alpha$ определен как $(1+s)^\alpha=1+\frac{\alpha}{1}s+\frac{\alpha(\alpha-1)}{1 \cdot 2}s^2+\ldots+\frac{\alpha(\alpha-1)\ldots(\alpha-n+1)}{1 \cdot 2 \cdot\ldots\cdot n}s^n+\ldots$. Докажите, что $(1+s)^\alpha(1+s)^\beta=(1+s)^{\alpha+\beta}$.&lt;br /&gt;
# Формальный степенной ряд $\ln\left(\frac{1}{1-s}\right)$ определен как $\ln\left(\frac{1}{1-s}\right)=s+\frac{1}{2}s^2+\frac{1}{3}s^3+\ldots+\frac{1}{n}s^n+\ldots$. Докажите, что $\exp\left(\ln\left(\frac{1}{1-s}\right)\right)=(1-s)^{-1}$.&lt;br /&gt;
# Пусть $B(s) = b_1s+b_2s^2+b_3s^3+\ldots+b_ns^n+\ldots$, причем $b_1\ne 0$. Пусть формальные степенные ряды $A(s)$ и $C(s)$ таковы, что $A(B(s)) = s$, $B(C(s))=s$. Докажите, что $A(s)=C(s)$ Этот ряд называется обратным к $B(s)$, обозначается как $B^{-1}(s)$.&lt;br /&gt;
# Будем называть нулем степенной ряд $0(s) = 0 + 0s + 0s^2 + \ldots$. Докажите, что $A(s) \ne 0(s)$, $B(s) \ne 0(s)$, то $A(s)B(s) \ne 0(s)$.&lt;br /&gt;
# Докажите, что $(A(s)B(s))' = A'(s)B(s) + A(s)B'(s)$.&lt;br /&gt;
# Докажите, что $\int(A'(s)B(s) + A(s)B'(s)) = A(s)B(s) - A(0)B(0)$.&lt;br /&gt;
# Найдите производящую функцию для последовательности $0 \cdot 1, 1 \cdot 2, 2 \cdot 3, 3 \cdot 4, \ldots, (n - 1) \cdot n, \ldots$.&lt;br /&gt;
# Найдите производящую функцию для последовательности $1^2, 2^2, 3^2, \ldots, n^2, \ldots$.&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0 + a_1, a_1 + a_2, \ldots, a_k+a_{k+1}$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, a_0 + a_1, a_0 + a_1 + a_2, \ldots, \sum\limits_{i=0}^ka_i,\ldots$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, a_1b, a_2b^2, \ldots, a_kb^k, \ldots$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, 0, a_1, 0, a_2, 0, a_3 \ldots$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, a_2, a_4, a_6 \ldots$&lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_0+f_1+\ldots+f_n=f_{n+2}-1$.&lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_0+f_2+\ldots+f_{2n}=f_{2n+1}$.&lt;br /&gt;
# Найдите производящую функцию для замощений прямоугольника $2\times n$ доминошками и единичными клетками.&lt;br /&gt;
# Найдите производящую функцию для замощений прямоугольника $2\times n$ уголками (квадратами $2\times 2$ с вырезанной одной клеткой) и единичными клетками. &lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_1+f_3+\ldots+f_{2n-1}=f_{2n}-1$.&lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_0^2+f_1^2+f_2^2+\ldots+f_n^2=f_nf_{n+1}$.&lt;br /&gt;
# Найдите производящую функцию для чисел &amp;quot;трибоначчи&amp;quot; $f_0=f_1=f_2=1$, $f_n = f_{n-1}+f_{n-2}+f_{n-3}$.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентностью $f_0=f_1=f_2=1$, $f_n = f_{n-1}-2f_{n-3}$.&lt;br /&gt;
# Производящая функция называется рациональной, если она представима в виде отношения двух многочленов. Для производящих функций каждой из следующих последовательностей выясните, является ли она рациональной, если да, приведите ее представление в таком виде. Последовательность $1, -2, 3, -4, 5, \ldots$.&lt;br /&gt;
# Последовательность $2, -6, 12, \ldots, (-1)^k(k+1)(k+2),\ldots$&lt;br /&gt;
# Последовательность $0, 1, 4, 9, 16, 25, \ldots, k^2,\ldots$&lt;br /&gt;
# Последовательность $0, 1, 8, 27, 64, 125, \ldots, k^3,\ldots$&lt;br /&gt;
# Последовательность $0, 1, 2^s, 3^s, 4^s, 5^s, \ldots, k^s,\ldots$&lt;br /&gt;
# Последовательность $1, -4, 9, -16, \ldots, (-1)^k(k+1)^2,\ldots$&lt;br /&gt;
# Последовательность $1, 1, 4, 9, 25, \ldots, F_k^2,\ldots$&lt;br /&gt;
# Найдите производящую функцию для чисел Каталана.&lt;br /&gt;
# Путь Моцкина - путь, начинающийся в точке $(0, 0)$, составленный из векторов $(1, 1)$, $(1, 0)$, $(1, -1)$, не опускающийся ниже оси $OX$ и заканчивающийся в точке $(n, 0)$. Напишите рекуррентное соотношение для числа путей Моцкина, найдите производящую функцию для числа таких путей.&lt;br /&gt;
# Рассмотрим множество путей на прямой, начинающихся в 0, состоящих из шагов длины 1 вправо или влево. Будем называть такой путь блужданием. Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в 0.&lt;br /&gt;
# Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в 0 и не заходящих в отрицательную полупрямую. &lt;br /&gt;
# Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в фиксированной точке $N &amp;gt; 0$.&lt;br /&gt;
# Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в фиксированной точке $N &amp;gt; 0$ и не заходящих в отрицательную полупрямую.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентным соотношением $a_0 = 2$, $a_n = a_{n-1}^2$.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентным соотношением $a_0 = 2$, $a_n = a_{n-1}^3$.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентным соотношением $a_0=a_1= 2$, $a_n = a_{n-1}\cdot a_{n - 2}$.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 5a_{n-1}-6a_{n-2}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 6a_{n-2}-a_{n-1}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 4a_{n-1}-4a_{n-2}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Петя заинтересовался, что будет, если последовательность, заданная линейным рекуррентным соотношением, имеет производящую фукнцию, в знаменателе которой стоит $Q(t)=(1-ct)(1+ct)$, ведь тогда асимптотическое поведение членов на четных и нечетных позициях разное. Разберитесь.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 2a_{n-1}-2a_{n-2}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Докажите, что если последовательность $a_n$ допускает представление в виде $a_n = \sum_i p_i(n)q_i^n$, где $p_i(n)$ - полиномы, и все $q_i$ различны, то такое представление единственно с точностью до порядка слагаемых.&lt;br /&gt;
# Используя результат из предыдушего задания, докажите, что формальный степенной ряд $\ln\left(\frac{1}{1-s}\right)=s+\frac{1}{2}s^2+\frac{1}{3}s^3+\ldots+\frac{1}{n}s^n+\ldots$ не представим в виде отношения двух полиномов.&lt;br /&gt;
# Произведением Адамара двух производящих функций $A(t)$ и $B(t)$ называется призводящая функция для ряда $C(t) = a_0b_0+a_1b_1t+a_2b_2t^2+\ldots+a_nb_nt^n+\ldots$. Докажите, что если $A(t)$ и $B(t)$ являются отношениями двух полиномов, то таким же свойством обладает и $C(t)$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1-x}$ и $\frac{1}{1-2x}$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1-2x}$ и $\frac{1}{1-3x}$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1+3x-x^2}$ и $\frac{1}{1-2x}$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1-2x-x^2}$ и $\frac{1}{1-2x}$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов. Пусть $M = MSet(A)$, а $P = Set(A)$. Докажите, что $M(t) = P(t)M(t^2)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Обозначим как $Seq^k(A)$ множество последовательностей длины $k$, каждый элемент которого является последовательностью из $k$ объектов. Найдите производящую функцию для $Seq^k(A)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Обозначим как $Seq^{\le k}(A)$ множество последовательностей длины $k$, каждый элемент которого является последовательностью из не более чем $k$ объектов. Найдите производящую функцию для $Seq^{\le k}(A)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Обозначим как $Seq^{\ge k}(A)$ множество последовательностей длины $k$, каждый элемент которого является последовательностью из не менее чем $k$ объектов. Найдите производящую функцию для $Seq^{\ge k}(A)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Пусть $\mathbb{N}$ - множество натуральных чисел, (вес числа $k$ равен $k$). Пусть $T \subset \mathbb{N}$, обозначим как $T(t)$ производящую функцию для множества $T$. Обозначим как $Seq_T(A)$ множество последовательностей элементов из $A$, где длина последовательности лежит в множестве $T$. Обозначим как $Z$ множество из одного элемента веса $1$. Обозначим как $C^T$ множество представлений в виде суммы, где порядок слагаемых важен и слагаемые выбраны из множества $T$. Осознайте, что $C^T = Seq(Seq_T(Z))$. Найдите производяющую функцию для $C^T$.&lt;br /&gt;
# Обозначим как $P^T$ множество разбиений на слагаемые, где порядок слагаемых не важен, а слагаемые выбраны из множества $T$. Осознайте, что $P^T = MSet(Seq_T(Z))$. Найдите производяющую функцию для $P^T$.&lt;br /&gt;
# Индекс Хирша. Докажите, что $\prod\limits_{n=1}^\infty\frac{1}{1-z^n}=\sum\limits_{n\ge 0}\frac{z^{n^2}}{((1-z)\cdots(1-z^n))^2}$.&lt;br /&gt;
# Докажите, что $\frac{1}{1-z}=\prod\limits_{j=0}^\infty(1+z^{2^j})$.&lt;br /&gt;
# Найдите производящую функцию для слов над $m$-буквенным алфавитом (вес каждой буквы равен 1, слова равен его длине).&lt;br /&gt;
# Обозначим как $W$ множество слов над алфавитом $\{a, b\}$. Осознайте, что $W=Seq\{a\}\times Seq(\{b\}\times Seq\{a\})$. Проверьте равенство для производящих функций.&lt;br /&gt;
# Обозначим как $W^{(k)}$ множество слов над алфавитом $\{a, b\}$, не содержащих $k$ букв $a$ подряд. Запишите $W^{(k)}$ через $Seq_T$ и $\times$. Найдите производящую функцию для $W^{(k)}$.&lt;br /&gt;
# Обобщите задание 60 на произвольный алфавит.&lt;br /&gt;
# Обобщите задание 61 на произвольный алфавит.&lt;br /&gt;
# Неявное задание КО. Пусть $A$, $B$ и $X$ - семейства комбинаторных объектов, причем $B \cap X = \varnothing$, $A = B \cup X$. Пусть производящие функции для $A$ и $B$ - $A(t)$ и $B(t)$, соответственно. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Неявное задание КО 2. Пусть $A$, $B$ и $X$ - семейства комбинаторных объектов, причем $A = B \times X$. Пусть производящие функции для $A$ и $B$ - $A(t)$ и $B(t)$, соответственно. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Неявное задание КО 3. Пусть $A$ и $X$ - семейства комбинаторных объектов, причем $A = Seq(X)$. Пусть производящая функция для $A$ - $A(t)$. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Неявное задание КО 4. Пусть $A$ и $X$ - семейства комбинаторных объектов, причем $A = MSet(X)$. Пусть производящая функция для $A$ - $A(t)$. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Экспоненциальная производящая функция для целочисленной последовательности называется функцией Гурвица. Докажите, что сумма, произведение, интеграл и производная функции Гурвица является функцией Гурвица.&lt;br /&gt;
# Докажите, что результат подстановки функции Гурвица в функцию Гурвица является функцией Гурвица&lt;br /&gt;
# Опишите класс помеченных объектов $seq(cyc(Z))$. Найдите его экспоненциальную производящую функцию.&lt;br /&gt;
# Будем обозначать $seq_T$, $cyc_T$, $set_T$ соответственно последовательности, циклы и множества, размер которых принадлежит множеству $T$. Опишите класс помеченных объектов $set(cyc_{\ge 1}(Z))$. Найдите его экспоненциальную производящую функцию.&lt;br /&gt;
# Опишите класс помеченных объектов $set(cyc_{1, 2}(Z))$. Найдите его экспоненциальную производящую функцию.&lt;br /&gt;
# Сюрьекции на $r$-элементное множество. Осознайте, что $seq_{=r}(set_{\ge 1}(Z))$ задаёт сюрьекции на $r$-элементное множество. Найдите экспоненциальную производящую функцию.&lt;br /&gt;
# Разбиения на $r$ множеств. Осознайте, что $set_{=r}(set_{\ge 1}(Z))$ задаёт разбиения на $r$-элементное множество. Найдите экспоненциальную производящую функцию. Что стоит при $z^n$?&lt;br /&gt;
# Гиперболический синус $\mathrm{sh}\,z$ равен $\frac{1}{2}(e^{z}-e^{-z})$. Гиперболический косинус $\mathrm{ch}\,z$ равен $\frac{1}{2}(e^{z}+e^{-z})$. Рассмотрим разбиения $n$-элементного множества на непустые подмножества. Для произвольных подмножеств экспоненциальная производящая функция равна $e^{e^z-1}$. Докажите, что для разбиений на нечетное число подмножеств экспоненциальная производящая функция равна $\mathrm{sh}(e^z-1)$.&lt;br /&gt;
# Докажите, что для разбиений на четное число подмножеств экспоненциальная производящая функция равна $\mathrm{ch}(e^z-1)$.&lt;br /&gt;
# Докажите, что для разбиений на произвольное число подмножеств, каждое из которых содержит нечетное число элементов, экспоненциальная производящая функция равна $e^{\mathrm{sh}\,z}$.&lt;br /&gt;
# Докажите, что для разбиений на произвольное число подмножеств, каждое из которых содержит четное число элементов, экспоненциальная производящая функция равна $e^{\mathrm{ch}\,z-1}$. Почему здесь в показателе степени есть $-1$, а в предыдущем задании нет?&lt;br /&gt;
# Обобщите четыре предыдущих задания. Как выглядят экспоненциальные производящие функции для разбиений на (не)четное число подмножеств, каждое из которых содержит (не)четное число элементов? (Необходимо дать четыре ответа для всех комбинаций)&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D0%94%D0%9C_2%D0%BA_2018_%D0%B2%D0%B5%D1%81%D0%BD%D0%B0&amp;diff=64367</id>
		<title>Список заданий по ДМ 2к 2018 весна</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D0%94%D0%9C_2%D0%BA_2018_%D0%B2%D0%B5%D1%81%D0%BD%D0%B0&amp;diff=64367"/>
				<updated>2018-03-14T19:21:52Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;# Формальный степенной ряд $\exp(s) = e^s$ определен как $e^s=1+\frac{1}{1!}s+\frac{1}{2!}s^2+\frac{1}{3!}s^3+\ldots+\frac{1}{n!}s^n+\ldots$. Логично, что $e^{-s}=1-\frac{1}{1!}s+\frac{1}{2!}s^2-\frac{1}{3!}s^3+\ldots+(-1)^n\frac{1}{n!}s^n+\ldots$. Докажите, используя определение умножения для степенных рядов, что $e^se^{-s}=1$.&lt;br /&gt;
# Формальный степенной ряд $(1+s)^\alpha$ определен как $(1+s)^\alpha=1+\frac{\alpha}{1}s+\frac{\alpha(\alpha-1)}{1 \cdot 2}s^2+\ldots+\frac{\alpha(\alpha-1)\ldots(\alpha-n+1)}{1 \cdot 2 \cdot\ldots\cdot n}s^n+\ldots$. Докажите, что $(1+s)^\alpha(1+s)^\beta=(1+s)^{\alpha+\beta}$.&lt;br /&gt;
# Формальный степенной ряд $\ln\left(\frac{1}{1-s}\right)$ определен как $\ln\left(\frac{1}{1-s}\right)=s+\frac{1}{2}s^2+\frac{1}{3}s^3+\ldots+\frac{1}{n}s^n+\ldots$. Докажите, что $\exp\left(\ln\left(\frac{1}{1-s}\right)\right)=(1-s)^{-1}$.&lt;br /&gt;
# Пусть $B(s) = b_1s+b_2s^2+b_3s^3+\ldots+b_ns^n+\ldots$, причем $b_1\ne 0$. Пусть формальные степенные ряды $A(s)$ и $C(s)$ таковы, что $A(B(s)) = s$, $B(C(s))=s$. Докажите, что $A(s)=C(s)$ Этот ряд называется обратным к $B(s)$, обозначается как $B^{-1}(s)$.&lt;br /&gt;
# Будем называть нулем степенной ряд $0(s) = 0 + 0s + 0s^2 + \ldots$. Докажите, что $A(s) \ne 0(s)$, $B(s) \ne 0(s)$, то $A(s)B(s) \ne 0(s)$.&lt;br /&gt;
# Докажите, что $(A(s)B(s))' = A'(s)B(s) + A(s)B'(s)$.&lt;br /&gt;
# Докажите, что $\int(A'(s)B(s) + A(s)B'(s)) = A(s)B(s) - A(0)B(0)$.&lt;br /&gt;
# Найдите производящую функцию для последовательности $0 \cdot 1, 1 \cdot 2, 2 \cdot 3, 3 \cdot 4, \ldots, (n - 1) \cdot n, \ldots$.&lt;br /&gt;
# Найдите производящую функцию для последовательности $1^2, 2^2, 3^2, \ldots, n^2, \ldots$.&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0 + a_1, a_1 + a_2, \ldots, a_k+a_{k+1}$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, a_0 + a_1, a_0 + a_1 + a_2, \ldots, \sum\limits_{i=0}^ka_i,\ldots$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, a_1b, a_2b^2, \ldots, a_kb^k, \ldots$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, 0, a_1, 0, a_2, 0, a_3 \ldots$&lt;br /&gt;
# Последовательность $a_0, a_1, a_2, \ldots, a_k, \ldots$ имеет производящую функцию $A(s)=a_0+a_1s+a_2s^2+\ldots$. Найдите производящую функцию последовательности $a_0, a_2, a_4, a_6 \ldots$&lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_0+f_1+\ldots+f_n=f_{n+2}-1$.&lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_0+f_2+\ldots+f_{2n}=f_{2n+1}$.&lt;br /&gt;
# Найдите производящую функцию для замощений прямоугольника $2\times n$ доминошками и единичными клетками.&lt;br /&gt;
# Найдите производящую функцию для замощений прямоугольника $2\times n$ уголками (квадратами $2\times 2$ с вырезанной одной клеткой) и единичными клетками. &lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_1+f_3+\ldots+f_{2n-1}=f_{2n}-1$.&lt;br /&gt;
# Пользуясь производящей функцией для чисел Фибоначчи, докажите утверждение, что $f_0^2+f_1^2+f_2^2+\ldots+f_n^2=f_nf_{n+1}$.&lt;br /&gt;
# Найдите производящую функцию для чисел &amp;quot;трибоначчи&amp;quot; $f_0=f_1=f_2=1$, $f_n = f_{n-1}+f_{n-2}+f_{n-3}$.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентностью $f_0=f_1=f_2=1$, $f_n = f_{n-1}-2f_{n-3}$.&lt;br /&gt;
# Производящая функция называется рациональной, если она представима в виде отношения двух многочленов. Для производящих функций каждой из следующих последовательностей выясните, является ли она рациональной, если да, приведите ее представление в таком виде. Последовательность $1, -2, 3, -4, 5, \ldots$.&lt;br /&gt;
# Последовательность $2, -6, 12, \ldots, (-1)^k(k+1)(k+2),\ldots$&lt;br /&gt;
# Последовательность $0, 1, 4, 9, 16, 25, \ldots, k^2,\ldots$&lt;br /&gt;
# Последовательность $0, 1, 8, 27, 64, 125, \ldots, k^3,\ldots$&lt;br /&gt;
# Последовательность $0, 1, 2^s, 3^s, 4^s, 5^s, \ldots, k^s,\ldots$&lt;br /&gt;
# Последовательность $1, -4, 9, -16, \ldots, (-1)^k(k+1)^2,\ldots$&lt;br /&gt;
# Последовательность $1, 1, 4, 9, 25, \ldots, F_k^2,\ldots$&lt;br /&gt;
# Найдите производящую функцию для чисел Каталана.&lt;br /&gt;
# Путь Моцкина - путь, начинающийся в точке $(0, 0)$, составленный из векторов $(1, 1)$, $(1, 0)$, $(1, -1)$, не опускающийся ниже оси $OX$ и заканчивающийся в точке $(n, 0)$. Напишите рекуррентное соотношение для числа путей Моцкина, найдите производящую функцию для числа таких путей.&lt;br /&gt;
# Рассмотрим множество путей на прямой, начинающихся в 0, состоящих из шагов длины 1 вправо или влево. Будем называть такой путь блужданием. Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в 0.&lt;br /&gt;
# Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в 0 и не заходящих в отрицательную полупрямую. &lt;br /&gt;
# Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в фиксированной точке $N &amp;gt; 0$.&lt;br /&gt;
# Найдите рекуррентную формулу и производящую функцию для числа блужданий из $n$ шагов, оканчивающихся в фиксированной точке $N &amp;gt; 0$ и не заходящих в отрицательную полупрямую.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентным соотношением $a_0 = 2$, $a_n = a_{n-1}^2$.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентным соотношением $a_0 = 2$, $a_n = a_{n-1}^3$.&lt;br /&gt;
# Найдите производящую функцию для последовательности, заданной рекуррентным соотношением $a_0=a_1= 2$, $a_n = a_{n-1}\cdot a_{n - 2}$.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 5a_{n-1}-6a_{n-2}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 6a_{n-2}-a_{n-1}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 4a_{n-1}-4a_{n-2}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Петя заинтересовался, что будет, если последовательность, заданная линейным рекуррентным соотношением, имеет производящую фукнцию, в знаменателе которой стоит $Q(t)=(1-ct)(1+ct)$, ведь тогда асимптотическое поведение членов на четных и нечетных позициях разное. Разберитесь.&lt;br /&gt;
# Последовательность задана рекуррентным соотношением $a_0=a_1=1$, $a_n = 2a_{n-1}-2a_{n-2}$. Оцените асимптотическое поведение $a_n$ при $n\to+\infty$.&lt;br /&gt;
# Докажите, что если последовательность $a_n$ допускает представление в виде $a_n = \sum_i p_i(n)q_i^n$, где $p_i(n)$ - полиномы, и все $q_i$ различны, то такое представление единственно с точностью до порядка слагаемых.&lt;br /&gt;
# Используя результат из предыдушего задания, докажите, что формальный степенной ряд $\ln\left(\frac{1}{1-s}\right)=s+\frac{1}{2}s^2+\frac{1}{3}s^3+\ldots+\frac{1}{n}s^n+\ldots$ не представим в виде отношения двух полиномов.&lt;br /&gt;
# Произведением Адамара двух производящих функций $A(t)$ и $B(t)$ называется призводящая функция для ряда $C(t) = a_0b_0+a_1b_1t+a_2b_2t^2+\ldots+a_nb_nt^n+\ldots$. Докажите, что если $A(t)$ и $B(t)$ являются отношениями двух полиномов, то таким же свойством обладает и $C(t)$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1-x}$ и $\frac{1}{1-2x}$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1-2x}$ и $\frac{1}{1-3x}$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1+3x-x^2}$ и $\frac{1}{1-2x}$.&lt;br /&gt;
# Найдите произведение Адамара $\frac{1}{1-2x-x^2}$ и $\frac{1}{1-2x}$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов. Пусть $M = MSet(A)$, а $P = Set(A)$. Докажите, что $M(t) = P(t)M(t^2)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Обозначим как $Seq^k(A)$ множество последовательностей длины $k$, каждый элемент которого является последовательностью из $k$ объектов. Найдите производящую функцию для $Seq^k(A)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Обозначим как $Seq^{\le k}(A)$ множество последовательностей длины $k$, каждый элемент которого является последовательностью из не более чем $k$ объектов. Найдите производящую функцию для $Seq^{\le k}(A)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Обозначим как $Seq^{\ge k}(A)$ множество последовательностей длины $k$, каждый элемент которого является последовательностью из не менее чем $k$ объектов. Найдите производящую функцию для $Seq^{\ge k}(A)$.&lt;br /&gt;
# Пусть $A$ - семейство комбинаторных объектов с производящей функцией $A(t)$. Пусть $\mathbb{N}$ - множество натуральных чисел, (вес числа $k$ равен $k$). Пусть $T \subset \mathbb{N}$, обозначим как $T(t)$ производящую функцию для множества $T$. Обозначим как $Seq_T(A)$ множество последовательностей элементов из $A$, где длина последовательности лежит в множестве $T$. Обозначим как $Z$ множество из одного элемента веса $1$. Обозначим как $C^T$ множество представлений в виде суммы, где порядок слагаемых важен и слагаемые выбраны из множества $T$. Осознайте, что $C^T = Seq(Seq_T(Z))$. Найдите производяющую функцию для $C^T$.&lt;br /&gt;
# Обозначим как $P^T$ множество разбиений на слагаемые, где порядок слагаемых не важен, а слагаемые выбраны из множества $T$. Осознайте, что $P^T = MSet(Seq_T(Z))$. Найдите производяющую функцию для $P^T$.&lt;br /&gt;
# Индекс Хирша. Докажите, что $\prod\limits_{n=1}^\infty\frac{1}{1-z^n}=\sum\limits_{n\ge 0}\frac{z^{n^2}}{((1-z)\cdots(1-z^n))^2}$.&lt;br /&gt;
# Докажите, что $\frac{1}{1-z}=\prod\limits_{j=0}^\infty(1+z^{2^j})$.&lt;br /&gt;
# Найдите производящую функцию для слов над $m$-буквенным алфавитом (вес каждой буквы равен 1, слова равен его длине).&lt;br /&gt;
# Обозначим как $W$ множество слов над алфавитом $\{a, b\}$. Осознайте, что $W=Seq\{a\}\times Seq(\{b\}\times Seq\{a\})$. Проверьте равенство для производящих функций.&lt;br /&gt;
# Обозначим как $W^{(k)}$ множество слов над алфавитом $\{a, b\}$, не содержащих $k$ букв $a$ подряд. Запишите $W^(k)$ через $Seq_T$ и $\times$. Найдите производящую функцию для $W^{(k)}$.&lt;br /&gt;
# Обобщите задание 60 на произвольный алфавит.&lt;br /&gt;
# Обобщите задание 61 на произвольный алфавит.&lt;br /&gt;
# Неявное задание. Пусть $A$, $B$ и $X$ - семейства комбинаторных объектов, причем $B \cap X = \varnothing$, $A = B \cup X$. Пусть производящие функции для $A$ и $B$ - $A(t)$ и $B(t)$, соответственно. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Неявное задание 2. Пусть $A$, $B$ и $X$ - семейства комбинаторных объектов, причем $A = B \times X$. Пусть производящие функции для $A$ и $B$ - $A(t)$ и $B(t)$, соответственно. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Неявное задание 3. Пусть $A$ и $X$ - семейства комбинаторных объектов, причем $A = Seq(X)$. Пусть производящая функция для $A$ - $A(t)$. Найдите производящую функцию $X(t)$.&lt;br /&gt;
# Неявное задание 4. Пусть $A$ и $X$ - семейства комбинаторных объектов, причем $A = MSet(X)$. Пусть производящая функция для $A$ - $A(t)$. Найдите производящую функцию $X(t)$.&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D1%85_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9&amp;diff=63860</id>
		<title>Произведение Адамара рациональных производящих функций</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D1%85_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9&amp;diff=63860"/>
				<updated>2018-03-01T15:21:33Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Рациональность произведения Адамара */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Одно из наиболее привлекательных свойств рациональных [[Производящая функция|производящих функций]] {{---}} их замкнутость относительно произведения Адамара.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition = '''Произведением Адамара''' (англ. ''Hadamard product'') производящих функций &amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + \dots&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B(s) = b_0 + b_1 s + b_2 s^2 + \dots&amp;lt;/tex&amp;gt; называется производящая функция &amp;lt;tex&amp;gt;A(s) \circ B(s) = (a_0  b_0) + (a_1  b_1) s + (a_2  b_2) s^2 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Таким образом, произведение Адамара двух последовательностей {{---}} это последовательность, состоящая из почленных произведений соответственных членов этих последовательностей. Необходимость в производящей функции для произведения Адамара уже встречалась: в [[Задача о счастливых билетах|задаче о числе счастливых билетов]] нам понадобилось вычислить сумму квадратов коэффициентов производящего многочлена &amp;lt;tex&amp;gt;A_3&amp;lt;/tex&amp;gt;. Эта необходимость возникает при перечислении пар объектов одинакового порядка: если число объектов первого типа равно &amp;lt;tex&amp;gt;a_n&amp;lt;/tex&amp;gt;, а число объектов второго типа &amp;lt;tex&amp;gt;b_n&amp;lt;/tex&amp;gt; то число пар объектов, составленных из элементов первого и второго типа, равно &amp;lt;tex&amp;gt;a_n b_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Рациональность произведения Адамара==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=Производящая функция для последовательности &amp;lt;tex&amp;gt;a_0, a_1,&lt;br /&gt;
 a_2, \dots&amp;lt;/tex&amp;gt; рациональна тогда и только тогда, когда существуют такие числа &amp;lt;tex&amp;gt;q_1, \dots, q_l&amp;lt;/tex&amp;gt; и такие многочлены &amp;lt;tex&amp;gt;p_1(n),&lt;br /&gt;
 \dots, p_l(n)&amp;lt;/tex&amp;gt;, что начиная с некоторого номера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; &lt;br /&gt;
&amp;lt;tex&amp;gt;a_n = p_1(n) q_1^n + \dots + p_l(n) q_l^n.&amp;lt;/tex&amp;gt;&lt;br /&gt;
Выражение в правой части равенства называется '''квазимногочленом''' (англ. ''quasypolynomial'') от переменной &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Заметим прежде всего, что производящая функция &amp;lt;tex&amp;gt;(1 - q s)^{-k}&amp;lt;/tex&amp;gt; имеет вид&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(1 - q s)^{-k} = 1 - \begin{pmatrix} -k \\ 1 \end{pmatrix} q s + \begin{pmatrix} -k \\ 2 \end{pmatrix} q^{2} s^{2} - \begin{pmatrix} -k \\ 3 \end{pmatrix} q^{3} s^{3} + \dots = &amp;lt;/tex&amp;gt;&lt;br /&gt;
:::&amp;lt;tex&amp;gt; = 1+ \begin{pmatrix} k \\ 1 \end{pmatrix} q s + \begin{pmatrix} k+1 \\ 2 \end{pmatrix} q^{2} s^{2} + \begin{pmatrix} k+2 \\ 3 \end{pmatrix} q^{3} s^{3} + \dots =&amp;lt;/tex&amp;gt;&lt;br /&gt;
:::&amp;lt;tex&amp;gt; = 1 + \begin{pmatrix} k \\ k-1 \end{pmatrix} q s + \begin{pmatrix} k+1 \\ k-1 \end{pmatrix} q^{2} s^{2} + \begin{pmatrix} k+2 \\ k-1 \end{pmatrix}q^{3} s^{3} + \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициент при &amp;lt;tex&amp;gt;s^n&amp;lt;/tex&amp;gt; в этой производящей функции равен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\dfrac{(n + 1)(n + 2)\dots(n + k - 1)}{(k - 1)!} q^{n} = P_{k - 1}(n) q^{n}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;tex&amp;gt;P_{k - 1}(n)&amp;lt;/tex&amp;gt; {{---}} многочлен от &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; степени &amp;lt;tex&amp;gt;k - 1&amp;lt;/tex&amp;gt;. Всякая рациональная функция от переменной &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; представляется в виде линейной комбинации многочлена и элементарных дробей вида &amp;lt;tex&amp;gt;(1 - q_i s)^{-k_i}&amp;lt;/tex&amp;gt;, поэтому коэффициенты соответствующей производящей функции являются квазимногочленами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Наоборот, предположим, что коэффициенты производящей функции, начиная с некоторого номера, представляются в виде квазимногочлена. Покажем, что в случае квазимногочлена &amp;lt;tex&amp;gt;p(n) q^{n}&amp;lt;/tex&amp;gt; соответствующая производящая функция рациональна. Пусть степень многочлена &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt;k - 1&amp;lt;/tex&amp;gt;. Многочлены &amp;lt;tex&amp;gt;P_0, P_1, \dots, P_{k - 1}&amp;lt;/tex&amp;gt;, определенные равенством &amp;lt;tex&amp;gt;\dfrac{(n + 1)(n + 2)\dots(n + k - 1)}{(k - 1)!} q^{n} = P_{k - 1}(n) q^{n}&amp;lt;/tex&amp;gt;, образуют базис в пространстве многочленов степени не выше &amp;lt;tex&amp;gt; k - 1&amp;lt;/tex&amp;gt;. Действительно, любая последовательность многочленов степеней &amp;lt;tex&amp;gt;0, 1, \dots, k - 1&amp;lt;/tex&amp;gt; образует базис в этом пространстве. Поэтому многочлен &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; представляется в виде линейной комбинации многочленов &amp;lt;tex&amp;gt;P_i&amp;lt;/tex&amp;gt; и соответствующая производящая функция есть просто линейная комбинация функций &amp;lt;tex&amp;gt;(1 - q s)^{-j}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;j = 0, 1, \dots, k - 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Для произвольного квазимногочлена мы получаем линейную комбинацию функций такого вида при разных &amp;lt;tex&amp;gt;q_i&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Предположим, что производящие функции для последовательностей &amp;lt;tex&amp;gt;a_0, a_1, a_2, \dots&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_0, b_1, b_2, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + \dots&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B(s) = b_0 + b_1 s + b_2 s^2 + \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
являются рациональными. Значит производящая функция для их произведения Адамара &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) \circ B(s) = (a_0  b_0) + (a_1  b_1) s + (a_2  b_2) s^2 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
является тоже рациональной. Проще говоря, произведение Адамара двух рациональных производящих функций рационально.&lt;br /&gt;
&lt;br /&gt;
|proof= Для доказательства теоремы осталось заменить, что произведение квазимногочленов является квазимногочленом. Это утверждение непосредственно вытекает из формулы &amp;lt;tex&amp;gt;a_n = p_1(n) q_1^n + \dots + p_l(n) q_l^n.&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;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 26с. ISBN 978-5-94057-042-4&lt;br /&gt;
* [[wikipedia:en:Generating function transformation | Wikipedia {{---}} Generating function transformation]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%81%D1%87%D0%B0%D1%81%D1%82%D0%BB%D0%B8%D0%B2%D1%8B%D1%85_%D0%B1%D0%B8%D0%BB%D0%B5%D1%82%D0%B0%D1%85&amp;diff=63859</id>
		<title>Задача о счастливых билетах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%81%D1%87%D0%B0%D1%81%D1%82%D0%BB%D0%B8%D0%B2%D1%8B%D1%85_%D0%B1%D0%B8%D0%BB%D0%B5%D1%82%D0%B0%D1%85&amp;diff=63859"/>
				<updated>2018-03-01T15:13:43Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Способ с конечной суммой */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Троллейбусный (трамвайный) билет имеет номер, состоящий из шести цифр. Билет считается счастливым, если сумма первых трёх цифр равна сумме последних трёх, например, &amp;lt;tex&amp;gt;024321&amp;lt;/tex&amp;gt;. Известно, что количество счастливых билетов из шести цифр равно &amp;lt;tex&amp;gt;55252&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Для натурального &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; найти количество &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значных счастливых билетов &amp;lt;tex&amp;gt;L_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
__TOC__&lt;br /&gt;
== Общие идеи ==&lt;br /&gt;
Обозначим количество &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-значных чисел с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt; (число может содержать ведущие нули). &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значный счастливый билет состоит из двух частей: левой (&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; цифр) и правой (тоже &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; цифр), причём в обеих частях сумма цифр одинакова. Зафиксируем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-значное число с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; в левой части (всего таких чисел &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt;, значит это можно сделать &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt; способами). Для него будет существовать &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt; возможных вариантов числа в правой части, следовательно количество счастливых билетов с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; в одной из частей равно &amp;lt;tex&amp;gt;(D_n^k)^2&amp;lt;/tex&amp;gt;. Значит общее число билетов равно &amp;lt;tex&amp;gt;L_n = \sum\limits_{k=0}^{9n} (D_{n}^{k})^2&amp;lt;/tex&amp;gt;. Верхний индекс суммирования равен &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;, так как максимальная сумма цифр в одной части билета равна &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;. Также можно сопоставить счастливому билету &amp;lt;tex&amp;gt;a_1a_2\ldots a_n b_1b_2 \ldots b_n&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значное число с суммой &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;a_1a_2\ldots a_n (9-b_1)(9-b_2) \ldots (9-b_n)&amp;lt;/tex&amp;gt;, причем это соответствие взаимно-однозначно, значит множества счастливых билетов и &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значных чисел с суммой &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;  равномощны, поэтому &amp;lt;tex&amp;gt;L_n=D_{2n}^{9n}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
== Метод динамического программирования ==&lt;br /&gt;
Научимся вычислять &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;D_0^k=\begin{cases}1,&amp;amp;k=0\\0,&amp;amp;k&amp;gt;0\end{cases}&amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;n&amp;gt;0&amp;lt;/tex&amp;gt; количество &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-значных чисел с суммой цифр &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; можно выразить через количество &amp;lt;tex&amp;gt;(n-1)&amp;lt;/tex&amp;gt;-значных чисел, добавляя к ним &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ю цифру, которая может быть равна &amp;lt;tex&amp;gt;0, 1, \ldots, 9&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;D_n^k=\sum\limits_{j=0}^{9}D_{n-1}^{k-j}&amp;lt;/tex&amp;gt;. Ответ {{---}} в &amp;lt;tex&amp;gt;D_{2n}^{9n}&amp;lt;/tex&amp;gt;, алгоритм будет работать за &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Метод производящей функции ==&lt;br /&gt;
Выпишем производящую функцию &amp;lt;tex&amp;gt;G(z)&amp;lt;/tex&amp;gt;, коэффициент при &amp;lt;tex&amp;gt;z^k&amp;lt;/tex&amp;gt; у которой будет равен &amp;lt;tex&amp;gt;D_1^k&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
G(z) = 1+z+z^2+z^3+z^4+z^5+z^6+z^7+z^8+z^9.&amp;lt;/tex&amp;gt;&lt;br /&gt;
Действительно, однозначное число с суммой цифр &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;k=0,\ldots,9&amp;lt;/tex&amp;gt;) можно представить одним способом. Для &amp;lt;tex&amp;gt;k&amp;gt;9&amp;lt;/tex&amp;gt; — ноль способов. Заметим, что &amp;lt;tex&amp;gt;G^n(z)&amp;lt;/tex&amp;gt; — производящая функция для чисел &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt;, поскольку коэффициент при &amp;lt;tex&amp;gt;z^k&amp;lt;/tex&amp;gt; получается перебором всех возможных комбинаций из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; цифр, равных в сумме &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. Ответом на задачу будет &amp;lt;tex&amp;gt;[z^{9n}]G^{2n}(z)&amp;lt;/tex&amp;gt;. Перепишем производящую функцию в ином виде: &amp;lt;tex&amp;gt;&lt;br /&gt;
G(z) = 1+z+\ldots+z^9 = \dfrac{1-z^{10}}{1-z}&lt;br /&gt;
&amp;lt;/tex&amp;gt; и получим, что &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;G^{2n}(z)=(1-z^{10})^{2n}(1-z)^{-2n}=\sum\limits_{k=0}^{2n}\binom{2n}{k}(-z^{10})^k\sum\limits_{j=0}^{\infty}\binom{-2n}{j}(-z)^j&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{-2n}{k}=(-1)^k\binom{2n+k-1}{k}&amp;lt;/tex&amp;gt;, понятно, что &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;[z^{9n}]G^{2n}(z)=\sum\limits_{j=0}^{\lfloor{\frac{9n}{10}}\rfloor}(-1)^j\binom{2n}{j}\binom{11n-10j-1}{9n-10j}&amp;lt;/tex&amp;gt;, что при &amp;lt;tex&amp;gt;n=3&amp;lt;/tex&amp;gt; дает &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{6}{0}\binom{32}{27}-\binom{6}{1}\binom{22}{17}+\binom{6}{2}\binom{12}{7}=55252&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Решение с помощью [[Формула включения-исключения | формулы включения-исключения]]==&lt;br /&gt;
Как мы заметили раньше, ответ на задачу равен количеству шестизначных билетов с суммой &amp;lt;tex&amp;gt;27&amp;lt;/tex&amp;gt;. Рассмотрим расстановки целых неотрицательных чисел на шести позициях, дающих в сумме &amp;lt;tex&amp;gt;27&amp;lt;/tex&amp;gt;; обозначим их множество &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Выделим шесть его подмножеств &amp;lt;tex&amp;gt;C_i, i = 1 \ldots 6&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е множество состоит из расстановок, у которых в &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-й позиции стоит число, не меньшее &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt;. Число счастливых билетов равно числу расстановок, не принадлежащих ни одному из множеств. Расстановке &amp;lt;tex&amp;gt;(a_1,a_2 \ldots a_n)&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; сопоставим сочетание с повторениями &amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B5#.D0.A1.D0.BE.D1.87.D0.B5.D1.82.D0.B0.D0.BD.D0.B8.D1.8F_.D1.81_.D0.BF.D0.BE.D0.B2.D1.82.D0.BE.D1.80.D0.B5.D0.BD.D0.B8.D1.8F.D0.BC.D0.B8 Сочетание — Википедия]&amp;lt;/ref&amp;gt; из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, в котором &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-й элемент повторяется &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; раз. Так как это сопоставление взаимно-однозначно, количество расстановок равно количеству сочетаний с повторениями, т.е. &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{n+k-1}{n-1}&amp;lt;/tex&amp;gt;. Число &amp;lt;tex&amp;gt;\left\vert{A}\right\vert&amp;lt;/tex&amp;gt; всех расстановок неотрицательных целых чисел с суммой &amp;lt;tex&amp;gt;27&amp;lt;/tex&amp;gt; в шесть позиций равно &amp;lt;tex  dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{32}{5}&amp;lt;/tex&amp;gt;. Число расстановок &amp;lt;tex&amp;gt;\left\vert{C_i}\right\vert&amp;lt;/tex&amp;gt; одинаково для всех &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и равно &amp;lt;tex  dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{22}{5}&amp;lt;/tex&amp;gt;. В самом деле, мы можем поставить в &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю позицию число &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt;, а оставшуюся сумму &amp;lt;tex&amp;gt;17&amp;lt;/tex&amp;gt; произвольно распределить по шести позициям. Аналогично, число расстановок &amp;lt;tex&amp;gt;\left\vert{C_i \cap C_j}\right\vert&amp;lt;/tex&amp;gt; одинаково для любой пары &amp;lt;tex&amp;gt;i, j, i \neq j&amp;lt;/tex&amp;gt; и равно &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{12}{5}&amp;lt;/tex&amp;gt;: мы выбираем две позиции и ставим в них &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt; и произвольно распределяем оставшуюся сумму &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; по шести позициям. Таким образом, искомое количество расстановок равно &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\left\vert{A}\right\vert - \binom{6}{1}\left\vert{C_i}\right\vert+\binom{6}{2}\left\vert{C_i \cap  C_j}\right\vert = \binom{32}{5}-6\binom{22}{5}+15\binom{12}{5} = 55252&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Решение путем интегрирования ==&lt;br /&gt;
Рассмотрим многочлен Лорана (т.е. многочлен, в котором допускаются отрицательные степени) &amp;lt;tex&amp;gt;H(z)=G^3(z)G^3(1/z)&amp;lt;/tex&amp;gt;. Заметим, что его свободный член равен &amp;lt;tex&amp;gt;\sum\limits_{i=0}^{27}[z^i]G^3(z)\cdot [z^{-i}]G^3(z^{-1})=\sum\limits_{i=0}^{27}(D_3^i)^2&amp;lt;/tex&amp;gt;. Воспользуемся теоремой Коши &amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D1%83%D0%BB%D0%B0_%D0%9A%D0%BE%D1%88%D0%B8 Интегральная формула Коши — Википедия]&lt;br /&gt;
&amp;lt;/ref&amp;gt; из комплексного анализа:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1 &lt;br /&gt;
|author=Коши&lt;br /&gt;
|statement=Для любого многочлена Лорана &amp;lt;tex&amp;gt;p(z)&amp;lt;/tex&amp;gt; его свободный член &amp;lt;tex&amp;gt;p_0&amp;lt;/tex&amp;gt; равен &lt;br /&gt;
: &amp;lt;tex&amp;gt;p_0=\dfrac{1}{2\pi i}{\displaystyle \int} \dfrac{p(z)}{z} dz&amp;lt;/tex&amp;gt;, где интегрирование происходит по любой окружности, ориентированной против часовой стрелки и содержащей внутри себя начало координат.&lt;br /&gt;
}}&lt;br /&gt;
Упростим многочлен &amp;lt;tex&amp;gt;H(z)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
: &amp;lt;tex&amp;gt;H(z)=\left( \dfrac{1-z^{10}}{1-z} \right) ^3\left(\dfrac{1-z^{-10}}{1-z^{-1}}\right)^3=\left(\dfrac{2-z^{10}-z^{-10}}{2-z-z^{-1}}\right)^3&amp;lt;/tex&amp;gt; и применим замену &amp;lt;tex&amp;gt;z=e^{i\phi}&amp;lt;/tex&amp;gt;:&lt;br /&gt;
: &amp;lt;tex&amp;gt;p_0=\dfrac{1}{2\pi}\displaystyle\int\limits_0^{2\pi}\left(\dfrac{2-e^{10i\phi}-e^{-10i\phi}}{2-e^{i\phi}-e^{-i\phi}}\right)^3d\phi=\dfrac{1}{2\pi}\displaystyle\int\limits_0^{2\pi}\left(\dfrac{2-2\cos(10\phi)}{2-2cos\phi}\right)^3d\phi=\dfrac{1}{2\pi}\displaystyle\int\limits_{0}^{2\pi}\left(\dfrac{\sin^2(5\phi)}{\sin^2(\frac{\phi}{2})}\right)^3d\phi=\dfrac{1}{\pi}\displaystyle\int\limits_0^{\pi}\left(\dfrac{\sin(10\phi)}{\sin\phi}\right)^6d\phi=\dfrac{1}{\pi}\displaystyle\int\limits_{-\pi/2}^{\pi/2}\left(\dfrac{\sin(10\phi)}{\sin\phi}\right)^6d\phi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим функцию &amp;lt;tex&amp;gt;f(\phi)=\dfrac{\sin(10\phi)}{\sin\phi}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\left[-\dfrac{\pi}{2},\dfrac{\pi}{2}\right]&amp;lt;/tex&amp;gt;. Вне отрезка &amp;lt;tex&amp;gt;\left[\dfrac{-\pi}{10},\dfrac{\pi}{10}\right]&lt;br /&gt;
 f(\phi) \leqslant \dfrac{1}{\sin\frac{\pi}{10}}\approx 3&amp;lt;/tex&amp;gt;, значит интеграл по этой части не больше &amp;lt;tex&amp;gt;3^6\pi \approx 2300&amp;lt;/tex&amp;gt;, основная часть сосредоточена на &amp;lt;tex&amp;gt;\left[-\dfrac{\pi}{10},\dfrac{\pi}{10}\right]&amp;lt;/tex&amp;gt;. Оценим интеграл по этому промежутку с помощью метода стационарной фазы.  &amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%81%D1%82%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B9_%D1%84%D0%B0%D0%B7%D1%8B Метод стационарной фазы — Википедия]&amp;lt;/ref&amp;gt; Этот метод позволяет оценить значение интеграла&lt;br /&gt;
: &amp;lt;tex&amp;gt;\displaystyle\int\limits_{-\pi/10}^{\pi/10}f^td\phi=\displaystyle\int\limits_{-\pi/10}^{\pi/10}e^{t\ln{f}}d\phi&amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;t \rightarrow \infty&amp;lt;/tex&amp;gt; значение интеграла определяется поведением его фазы, т.е. &amp;lt;tex&amp;gt;\ln{f}&amp;lt;/tex&amp;gt;, в окрестности стационарной точки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; (точки, где &amp;lt;tex&amp;gt;(\ln{f})'=0&amp;lt;/tex&amp;gt;, или, что то же самое, &amp;lt;tex&amp;gt;f'=0&amp;lt;/tex&amp;gt;). Вблизи &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;f(\phi) \approx 10 \left(1 - \dfrac{33}{2}\phi^2\right)&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;\ln{f}(\phi) \approx \ln 10 - \dfrac{33}{2}\phi^2&amp;lt;/tex&amp;gt;. При больших &amp;lt;tex&amp;gt;t &amp;lt;/tex&amp;gt; получим&lt;br /&gt;
: &amp;lt;tex&amp;gt;{\displaystyle\int\limits_{-\pi/10}^{\pi/10}\exp(t(\ln 10 - \frac{33}{2}\phi^2))d\phi=10^t \int\limits_{-\pi/10}^{\pi/10}\exp(-\frac{33}{2}\phi^2)d\phi=\sqrt{\dfrac{\pi}{66t}} \cdot \mathrm{erf}\left(\sqrt{\dfrac{33t}{2}\phi}\right)\bigg\rvert_{-\pi/10}^{\pi/10}}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathrm{erf}(z)&amp;lt;/tex&amp;gt; {{---}} функция ошибок &amp;lt;ref&amp;gt;[http://mathworld.wolfram.com/Erf.html Erf -- from Wolfram MathWorld]&amp;lt;/ref&amp;gt;. Заметим, что при &amp;lt;tex&amp;gt;z &amp;gt; 2 &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathrm{erf}(z) \approx 1&amp;lt;/tex&amp;gt;, поэтому интеграл примерно равен &amp;lt;tex&amp;gt;10^t \sqrt{\dfrac{2\pi}{33t}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Полагая &amp;lt;tex&amp;gt;t=6&amp;lt;/tex&amp;gt; и вспоминая выражение для &amp;lt;tex&amp;gt;p_0&amp;lt;/tex&amp;gt;, получаем приближенное равенство:&lt;br /&gt;
: &amp;lt;tex&amp;gt;p_0 \approx \dfrac{10^6}{3\sqrt{11\pi}} \approx 56700&amp;lt;/tex&amp;gt;&lt;br /&gt;
Этот результат с хорошей точностью (отклонение составляет не более &amp;lt;tex&amp;gt;3\%&amp;lt;/tex&amp;gt;) приближает искомое значение.&lt;br /&gt;
&lt;br /&gt;
== Способ с конечной суммой == &lt;br /&gt;
Рассмотрим функцию &amp;lt;tex&amp;gt;g(\phi)=H(e^{i\phi})=\left(\dfrac{\sin{5\phi}}{\sin{\frac{\pi}{2}}}\right)^6&amp;lt;/tex&amp;gt;. Как доказано выше, &amp;lt;tex&amp;gt;L_6=\dfrac{1}{2\pi}\displaystyle\int\limits_0^{2\pi}g(\phi)d\phi&amp;lt;/tex&amp;gt;. Для интеграла можно выписать приближенную формулу и получить &amp;lt;tex&amp;gt;L_6 \approx \dfrac{1}{N}\sum\limits_{k=0}^{N-1}g(\dfrac{2\pi k}{N})&amp;lt;/tex&amp;gt;. Интересно, что при достаточно большом &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; это равенство становится точным.&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=При &amp;lt;tex&amp;gt;N \geqslant 28&amp;lt;/tex&amp;gt; и любом &amp;lt;tex&amp;gt;\phi_0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;L_6 = \dfrac{1}{N}\sum\limits_{k=0}^{N-1}g(\phi_k)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\phi_k=\phi_0+\dfrac{2\pi k}{N}, k &amp;gt; 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=По определению, &amp;lt;tex&amp;gt;g(\phi)=\sum\limits_{j=-27}^{27}a_je^{ij\phi}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_j&amp;lt;/tex&amp;gt; {{---}} коэффициенты многочлена &amp;lt;tex&amp;gt;H(z)&amp;lt;/tex&amp;gt;. Обозначим &lt;br /&gt;
&amp;lt;tex&amp;gt;r(\phi)=\sum\limits_{j=1}^{27}a_j(e^{ij\phi}+e^{-ij\phi}), g(\phi)=a_0+r(\phi)&amp;lt;/tex&amp;gt;. Докажем, что &lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{k=0}^{N-1}g(\phi_k)=0&amp;lt;/tex&amp;gt;. Раскроем &amp;lt;tex&amp;gt;g(\phi_k)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
: &amp;lt;tex&amp;gt;{\displaystyle\sum\limits_{k=0}^{N-1}\sum\limits_{j=1}^{27}a_j\left(\exp\left(ij\left(\phi_0+\dfrac{2\pi k}{N}\right)\right) + \exp\left(-ij\left(\phi_0+\dfrac{2\pi k}{N}\right)\right)\right)=  e^{ij\phi_0}\sum\limits_{j=1}^{27}a_j\sum\limits_{k=0}^{N-1}\left(\exp\left(ij\dfrac{2\pi k}{N}\right) + \exp\left(-ij\dfrac{2\pi k}{N}\right)\right)}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
Рассмотрим внутреннюю сумму:&lt;br /&gt;
: &amp;lt;tex&amp;gt;{\displaystyle\sum\limits_{k=0}^{N-1}\left(\exp\left(\dfrac{2ijk\pi}{N}\right)+\exp\left(-\dfrac{2ijk\pi}{N}\right)\right)=\sum\limits_{k=0}^{N-1}\exp\left(\dfrac{2ijk\pi}{N}\right)+\sum\limits_{k=0}^{N-1}\exp\left(-\dfrac{2ijk\pi}{N}\right)}&amp;lt;/tex&amp;gt;. Получили две геометрические прогрессии со знаменателями, не равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;N&amp;gt;j \implies \exp\left(\dfrac{2ij\pi}{N}\right)\neq 1, \exp\left(-\dfrac{2ij\pi}{N}\right)\neq 1&amp;lt;/tex&amp;gt;. Значит искомая сумма равна &lt;br /&gt;
: &amp;lt;tex&amp;gt;\dfrac{1-\exp\left(2ij\pi\right)}{1-\exp\left(\dfrac{2ij\pi}{N}\right)}+\dfrac{1-\exp\left(-2ij\pi\right)}{1-\exp\left(-\dfrac{2ij\pi}{N}\right)}=0&amp;lt;/tex&amp;gt;, так как &amp;lt;tex&amp;gt;e^{2\pi i}=1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Таким образом,  &lt;br /&gt;
&amp;lt;tex&amp;gt;\dfrac{1}{N}\sum\limits_{k=0}^{N-1}g\left(\phi_k\right)=\dfrac{1}{N}\sum\limits_{k=0}^{N-1}\left(a_0+g\left(\phi_k\right)\right)=a_0&amp;lt;/tex&amp;gt;, &lt;br /&gt;
а свободный член &amp;lt;tex&amp;gt;H\left(z\right)&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;L_6&amp;lt;/tex&amp;gt;, как известно из предыдущего раздела.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Производящая функция]]&lt;br /&gt;
&lt;br /&gt;
* [[Динамическое программирование]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.genfunc.ru/theory/lucky/ Задача о счастливых билетах :: Производящие функции]&lt;br /&gt;
&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 144с. ISBN 978-5-94057-042-4&lt;br /&gt;
[[Категория:Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория:Комбинаторика]]&lt;br /&gt;
[[Категория:Производящие функции]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%81%D1%87%D0%B0%D1%81%D1%82%D0%BB%D0%B8%D0%B2%D1%8B%D1%85_%D0%B1%D0%B8%D0%BB%D0%B5%D1%82%D0%B0%D1%85&amp;diff=63858</id>
		<title>Задача о счастливых билетах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%81%D1%87%D0%B0%D1%81%D1%82%D0%BB%D0%B8%D0%B2%D1%8B%D1%85_%D0%B1%D0%B8%D0%BB%D0%B5%D1%82%D0%B0%D1%85&amp;diff=63858"/>
				<updated>2018-03-01T15:10:52Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Решение путем интегрирования */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Троллейбусный (трамвайный) билет имеет номер, состоящий из шести цифр. Билет считается счастливым, если сумма первых трёх цифр равна сумме последних трёх, например, &amp;lt;tex&amp;gt;024321&amp;lt;/tex&amp;gt;. Известно, что количество счастливых билетов из шести цифр равно &amp;lt;tex&amp;gt;55252&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Для натурального &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; найти количество &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значных счастливых билетов &amp;lt;tex&amp;gt;L_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
__TOC__&lt;br /&gt;
== Общие идеи ==&lt;br /&gt;
Обозначим количество &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-значных чисел с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt; (число может содержать ведущие нули). &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значный счастливый билет состоит из двух частей: левой (&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; цифр) и правой (тоже &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; цифр), причём в обеих частях сумма цифр одинакова. Зафиксируем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-значное число с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; в левой части (всего таких чисел &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt;, значит это можно сделать &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt; способами). Для него будет существовать &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt; возможных вариантов числа в правой части, следовательно количество счастливых билетов с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; в одной из частей равно &amp;lt;tex&amp;gt;(D_n^k)^2&amp;lt;/tex&amp;gt;. Значит общее число билетов равно &amp;lt;tex&amp;gt;L_n = \sum\limits_{k=0}^{9n} (D_{n}^{k})^2&amp;lt;/tex&amp;gt;. Верхний индекс суммирования равен &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;, так как максимальная сумма цифр в одной части билета равна &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;. Также можно сопоставить счастливому билету &amp;lt;tex&amp;gt;a_1a_2\ldots a_n b_1b_2 \ldots b_n&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значное число с суммой &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;a_1a_2\ldots a_n (9-b_1)(9-b_2) \ldots (9-b_n)&amp;lt;/tex&amp;gt;, причем это соответствие взаимно-однозначно, значит множества счастливых билетов и &amp;lt;tex&amp;gt;2n&amp;lt;/tex&amp;gt;-значных чисел с суммой &amp;lt;tex&amp;gt;9n&amp;lt;/tex&amp;gt;  равномощны, поэтому &amp;lt;tex&amp;gt;L_n=D_{2n}^{9n}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
== Метод динамического программирования ==&lt;br /&gt;
Научимся вычислять &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;D_0^k=\begin{cases}1,&amp;amp;k=0\\0,&amp;amp;k&amp;gt;0\end{cases}&amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;n&amp;gt;0&amp;lt;/tex&amp;gt; количество &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-значных чисел с суммой цифр &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; можно выразить через количество &amp;lt;tex&amp;gt;(n-1)&amp;lt;/tex&amp;gt;-значных чисел, добавляя к ним &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ю цифру, которая может быть равна &amp;lt;tex&amp;gt;0, 1, \ldots, 9&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;D_n^k=\sum\limits_{j=0}^{9}D_{n-1}^{k-j}&amp;lt;/tex&amp;gt;. Ответ {{---}} в &amp;lt;tex&amp;gt;D_{2n}^{9n}&amp;lt;/tex&amp;gt;, алгоритм будет работать за &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Метод производящей функции ==&lt;br /&gt;
Выпишем производящую функцию &amp;lt;tex&amp;gt;G(z)&amp;lt;/tex&amp;gt;, коэффициент при &amp;lt;tex&amp;gt;z^k&amp;lt;/tex&amp;gt; у которой будет равен &amp;lt;tex&amp;gt;D_1^k&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
G(z) = 1+z+z^2+z^3+z^4+z^5+z^6+z^7+z^8+z^9.&amp;lt;/tex&amp;gt;&lt;br /&gt;
Действительно, однозначное число с суммой цифр &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;k=0,\ldots,9&amp;lt;/tex&amp;gt;) можно представить одним способом. Для &amp;lt;tex&amp;gt;k&amp;gt;9&amp;lt;/tex&amp;gt; — ноль способов. Заметим, что &amp;lt;tex&amp;gt;G^n(z)&amp;lt;/tex&amp;gt; — производящая функция для чисел &amp;lt;tex&amp;gt;D_n^k&amp;lt;/tex&amp;gt;, поскольку коэффициент при &amp;lt;tex&amp;gt;z^k&amp;lt;/tex&amp;gt; получается перебором всех возможных комбинаций из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; цифр, равных в сумме &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. Ответом на задачу будет &amp;lt;tex&amp;gt;[z^{9n}]G^{2n}(z)&amp;lt;/tex&amp;gt;. Перепишем производящую функцию в ином виде: &amp;lt;tex&amp;gt;&lt;br /&gt;
G(z) = 1+z+\ldots+z^9 = \dfrac{1-z^{10}}{1-z}&lt;br /&gt;
&amp;lt;/tex&amp;gt; и получим, что &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;G^{2n}(z)=(1-z^{10})^{2n}(1-z)^{-2n}=\sum\limits_{k=0}^{2n}\binom{2n}{k}(-z^{10})^k\sum\limits_{j=0}^{\infty}\binom{-2n}{j}(-z)^j&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{-2n}{k}=(-1)^k\binom{2n+k-1}{k}&amp;lt;/tex&amp;gt;, понятно, что &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;[z^{9n}]G^{2n}(z)=\sum\limits_{j=0}^{\lfloor{\frac{9n}{10}}\rfloor}(-1)^j\binom{2n}{j}\binom{11n-10j-1}{9n-10j}&amp;lt;/tex&amp;gt;, что при &amp;lt;tex&amp;gt;n=3&amp;lt;/tex&amp;gt; дает &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{6}{0}\binom{32}{27}-\binom{6}{1}\binom{22}{17}+\binom{6}{2}\binom{12}{7}=55252&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Решение с помощью [[Формула включения-исключения | формулы включения-исключения]]==&lt;br /&gt;
Как мы заметили раньше, ответ на задачу равен количеству шестизначных билетов с суммой &amp;lt;tex&amp;gt;27&amp;lt;/tex&amp;gt;. Рассмотрим расстановки целых неотрицательных чисел на шести позициях, дающих в сумме &amp;lt;tex&amp;gt;27&amp;lt;/tex&amp;gt;; обозначим их множество &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Выделим шесть его подмножеств &amp;lt;tex&amp;gt;C_i, i = 1 \ldots 6&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е множество состоит из расстановок, у которых в &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-й позиции стоит число, не меньшее &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt;. Число счастливых билетов равно числу расстановок, не принадлежащих ни одному из множеств. Расстановке &amp;lt;tex&amp;gt;(a_1,a_2 \ldots a_n)&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел с суммой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; сопоставим сочетание с повторениями &amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B5#.D0.A1.D0.BE.D1.87.D0.B5.D1.82.D0.B0.D0.BD.D0.B8.D1.8F_.D1.81_.D0.BF.D0.BE.D0.B2.D1.82.D0.BE.D1.80.D0.B5.D0.BD.D0.B8.D1.8F.D0.BC.D0.B8 Сочетание — Википедия]&amp;lt;/ref&amp;gt; из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, в котором &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-й элемент повторяется &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; раз. Так как это сопоставление взаимно-однозначно, количество расстановок равно количеству сочетаний с повторениями, т.е. &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{n+k-1}{n-1}&amp;lt;/tex&amp;gt;. Число &amp;lt;tex&amp;gt;\left\vert{A}\right\vert&amp;lt;/tex&amp;gt; всех расстановок неотрицательных целых чисел с суммой &amp;lt;tex&amp;gt;27&amp;lt;/tex&amp;gt; в шесть позиций равно &amp;lt;tex  dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{32}{5}&amp;lt;/tex&amp;gt;. Число расстановок &amp;lt;tex&amp;gt;\left\vert{C_i}\right\vert&amp;lt;/tex&amp;gt; одинаково для всех &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и равно &amp;lt;tex  dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{22}{5}&amp;lt;/tex&amp;gt;. В самом деле, мы можем поставить в &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю позицию число &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt;, а оставшуюся сумму &amp;lt;tex&amp;gt;17&amp;lt;/tex&amp;gt; произвольно распределить по шести позициям. Аналогично, число расстановок &amp;lt;tex&amp;gt;\left\vert{C_i \cap C_j}\right\vert&amp;lt;/tex&amp;gt; одинаково для любой пары &amp;lt;tex&amp;gt;i, j, i \neq j&amp;lt;/tex&amp;gt; и равно &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\binom{12}{5}&amp;lt;/tex&amp;gt;: мы выбираем две позиции и ставим в них &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt; и произвольно распределяем оставшуюся сумму &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; по шести позициям. Таким образом, искомое количество расстановок равно &amp;lt;tex dpi=&amp;quot;140&amp;quot;&amp;gt;\left\vert{A}\right\vert - \binom{6}{1}\left\vert{C_i}\right\vert+\binom{6}{2}\left\vert{C_i \cap  C_j}\right\vert = \binom{32}{5}-6\binom{22}{5}+15\binom{12}{5} = 55252&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Решение путем интегрирования ==&lt;br /&gt;
Рассмотрим многочлен Лорана (т.е. многочлен, в котором допускаются отрицательные степени) &amp;lt;tex&amp;gt;H(z)=G^3(z)G^3(1/z)&amp;lt;/tex&amp;gt;. Заметим, что его свободный член равен &amp;lt;tex&amp;gt;\sum\limits_{i=0}^{27}[z^i]G^3(z)\cdot [z^{-i}]G^3(z^{-1})=\sum\limits_{i=0}^{27}(D_3^i)^2&amp;lt;/tex&amp;gt;. Воспользуемся теоремой Коши &amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D1%83%D0%BB%D0%B0_%D0%9A%D0%BE%D1%88%D0%B8 Интегральная формула Коши — Википедия]&lt;br /&gt;
&amp;lt;/ref&amp;gt; из комплексного анализа:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1 &lt;br /&gt;
|author=Коши&lt;br /&gt;
|statement=Для любого многочлена Лорана &amp;lt;tex&amp;gt;p(z)&amp;lt;/tex&amp;gt; его свободный член &amp;lt;tex&amp;gt;p_0&amp;lt;/tex&amp;gt; равен &lt;br /&gt;
: &amp;lt;tex&amp;gt;p_0=\dfrac{1}{2\pi i}{\displaystyle \int} \dfrac{p(z)}{z} dz&amp;lt;/tex&amp;gt;, где интегрирование происходит по любой окружности, ориентированной против часовой стрелки и содержащей внутри себя начало координат.&lt;br /&gt;
}}&lt;br /&gt;
Упростим многочлен &amp;lt;tex&amp;gt;H(z)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
: &amp;lt;tex&amp;gt;H(z)=\left( \dfrac{1-z^{10}}{1-z} \right) ^3\left(\dfrac{1-z^{-10}}{1-z^{-1}}\right)^3=\left(\dfrac{2-z^{10}-z^{-10}}{2-z-z^{-1}}\right)^3&amp;lt;/tex&amp;gt; и применим замену &amp;lt;tex&amp;gt;z=e^{i\phi}&amp;lt;/tex&amp;gt;:&lt;br /&gt;
: &amp;lt;tex&amp;gt;p_0=\dfrac{1}{2\pi}\displaystyle\int\limits_0^{2\pi}\left(\dfrac{2-e^{10i\phi}-e^{-10i\phi}}{2-e^{i\phi}-e^{-i\phi}}\right)^3d\phi=\dfrac{1}{2\pi}\displaystyle\int\limits_0^{2\pi}\left(\dfrac{2-2\cos(10\phi)}{2-2cos\phi}\right)^3d\phi=\dfrac{1}{2\pi}\displaystyle\int\limits_{0}^{2\pi}\left(\dfrac{\sin^2(5\phi)}{\sin^2(\frac{\phi}{2})}\right)^3d\phi=\dfrac{1}{\pi}\displaystyle\int\limits_0^{\pi}\left(\dfrac{\sin(10\phi)}{\sin\phi}\right)^6d\phi=\dfrac{1}{\pi}\displaystyle\int\limits_{-\pi/2}^{\pi/2}\left(\dfrac{\sin(10\phi)}{\sin\phi}\right)^6d\phi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим функцию &amp;lt;tex&amp;gt;f(\phi)=\dfrac{\sin(10\phi)}{\sin\phi}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\left[-\dfrac{\pi}{2},\dfrac{\pi}{2}\right]&amp;lt;/tex&amp;gt;. Вне отрезка &amp;lt;tex&amp;gt;\left[\dfrac{-\pi}{10},\dfrac{\pi}{10}\right]&lt;br /&gt;
 f(\phi) \leqslant \dfrac{1}{\sin\frac{\pi}{10}}\approx 3&amp;lt;/tex&amp;gt;, значит интеграл по этой части не больше &amp;lt;tex&amp;gt;3^6\pi \approx 2300&amp;lt;/tex&amp;gt;, основная часть сосредоточена на &amp;lt;tex&amp;gt;\left[-\dfrac{\pi}{10},\dfrac{\pi}{10}\right]&amp;lt;/tex&amp;gt;. Оценим интеграл по этому промежутку с помощью метода стационарной фазы.  &amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%81%D1%82%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B9_%D1%84%D0%B0%D0%B7%D1%8B Метод стационарной фазы — Википедия]&amp;lt;/ref&amp;gt; Этот метод позволяет оценить значение интеграла&lt;br /&gt;
: &amp;lt;tex&amp;gt;\displaystyle\int\limits_{-\pi/10}^{\pi/10}f^td\phi=\displaystyle\int\limits_{-\pi/10}^{\pi/10}e^{t\ln{f}}d\phi&amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;t \rightarrow \infty&amp;lt;/tex&amp;gt; значение интеграла определяется поведением его фазы, т.е. &amp;lt;tex&amp;gt;\ln{f}&amp;lt;/tex&amp;gt;, в окрестности стационарной точки &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; (точки, где &amp;lt;tex&amp;gt;(\ln{f})'=0&amp;lt;/tex&amp;gt;, или, что то же самое, &amp;lt;tex&amp;gt;f'=0&amp;lt;/tex&amp;gt;). Вблизи &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;f(\phi) \approx 10 \left(1 - \dfrac{33}{2}\phi^2\right)&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;\ln{f}(\phi) \approx \ln 10 - \dfrac{33}{2}\phi^2&amp;lt;/tex&amp;gt;. При больших &amp;lt;tex&amp;gt;t &amp;lt;/tex&amp;gt; получим&lt;br /&gt;
: &amp;lt;tex&amp;gt;{\displaystyle\int\limits_{-\pi/10}^{\pi/10}\exp(t(\ln 10 - \frac{33}{2}\phi^2))d\phi=10^t \int\limits_{-\pi/10}^{\pi/10}\exp(-\frac{33}{2}\phi^2)d\phi=\sqrt{\dfrac{\pi}{66t}} \cdot \mathrm{erf}\left(\sqrt{\dfrac{33t}{2}\phi}\right)\bigg\rvert_{-\pi/10}^{\pi/10}}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathrm{erf}(z)&amp;lt;/tex&amp;gt; {{---}} функция ошибок &amp;lt;ref&amp;gt;[http://mathworld.wolfram.com/Erf.html Erf -- from Wolfram MathWorld]&amp;lt;/ref&amp;gt;. Заметим, что при &amp;lt;tex&amp;gt;z &amp;gt; 2 &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathrm{erf}(z) \approx 1&amp;lt;/tex&amp;gt;, поэтому интеграл примерно равен &amp;lt;tex&amp;gt;10^t \sqrt{\dfrac{2\pi}{33t}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Полагая &amp;lt;tex&amp;gt;t=6&amp;lt;/tex&amp;gt; и вспоминая выражение для &amp;lt;tex&amp;gt;p_0&amp;lt;/tex&amp;gt;, получаем приближенное равенство:&lt;br /&gt;
: &amp;lt;tex&amp;gt;p_0 \approx \dfrac{10^6}{3\sqrt{11\pi}} \approx 56700&amp;lt;/tex&amp;gt;&lt;br /&gt;
Этот результат с хорошей точностью (отклонение составляет не более &amp;lt;tex&amp;gt;3\%&amp;lt;/tex&amp;gt;) приближает искомое значение.&lt;br /&gt;
&lt;br /&gt;
== Способ с конечной суммой == &lt;br /&gt;
Рассмотрим функцию &amp;lt;tex&amp;gt;g(\phi)=H(e^{i\phi})=\left(\dfrac{\sin{5\phi}}{\sin{\frac{\pi}{2}}}\right)^6&amp;lt;/tex&amp;gt;. Как доказано выше, &amp;lt;tex&amp;gt;L_6=\dfrac{1}{2\pi}\displaystyle\int_0^{2\pi}g(\phi)d\phi&amp;lt;/tex&amp;gt;. Для интеграла можно выписать приближенную формулу и получить &amp;lt;tex&amp;gt;L_6 \approx \dfrac{1}{N}\sum\limits_{k=0}^{N-1}g(\dfrac{2\pi k}{N})&amp;lt;/tex&amp;gt;. Интересно, что при достаточно большом &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; это равенство становится точным.&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=При &amp;lt;tex&amp;gt;N \geqslant 28&amp;lt;/tex&amp;gt; и любом &amp;lt;tex&amp;gt;\phi_0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;L_6 = \dfrac{1}{N}\sum\limits_{k=0}^{N-1}g(\phi_k)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\phi_k=\phi_0+\dfrac{2\pi k}{N}, k &amp;gt; 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=По определению, &amp;lt;tex&amp;gt;g(\phi)=\sum\limits_{j=-27}^{27}a_je^{ij\phi}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_j&amp;lt;/tex&amp;gt; {{---}} коэффициенты многочлена &amp;lt;tex&amp;gt;H(z)&amp;lt;/tex&amp;gt;. Обозначим &lt;br /&gt;
&amp;lt;tex&amp;gt;r(\phi)=\sum\limits_{j=1}^{27}a_j(e^{ij\phi}+e^{-ij\phi}), g(\phi)=a_0+r(\phi)&amp;lt;/tex&amp;gt;. Докажем, что &lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{k=0}^{N-1}g(\phi_k)=0&amp;lt;/tex&amp;gt;. Раскроем &amp;lt;tex&amp;gt;g(\phi_k)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
: &amp;lt;tex&amp;gt;{\displaystyle\sum\limits_{k=0}^{N-1}\sum\limits_{j=1}^{27}a_j\left(\exp\left(ij\left(\phi_0+\dfrac{2\pi k}{N}\right)\right) + \exp\left(-ij\left(\phi_0+\dfrac{2\pi k}{N}\right)\right)\right)=  e^{ij\phi_0}\sum\limits_{j=1}^{27}a_j\sum\limits_{k=0}^{N-1}\left(\exp\left(ij\dfrac{2\pi k}{N}\right) + \exp\left(-ij\dfrac{2\pi k}{N}\right)\right)}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
Рассмотрим внутреннюю сумму:&lt;br /&gt;
: &amp;lt;tex&amp;gt;{\displaystyle\sum\limits_{k=0}^{N-1}\left(\exp\left(\dfrac{2ijk\pi}{N}\right)+\exp\left(-\dfrac{2ijk\pi}{N}\right)\right)=\sum\limits_{k=0}^{N-1}\exp\left(\dfrac{2ijk\pi}{N}\right)+\sum\limits_{k=0}^{N-1}\exp\left(-\dfrac{2ijk\pi}{N}\right)}&amp;lt;/tex&amp;gt;. Получили две геометрические прогрессии со знаменателями, не равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;N&amp;gt;j \implies \exp\left(\dfrac{2ij\pi}{N}\right)\neq 1, \exp\left(-\dfrac{2ij\pi}{N}\right)\neq 1&amp;lt;/tex&amp;gt;. Значит искомая сумма равна &lt;br /&gt;
: &amp;lt;tex&amp;gt;\dfrac{1-\exp\left(2ij\pi\right)}{1-\exp\left(\dfrac{2ij\pi}{N}\right)}+\dfrac{1-\exp\left(-2ij\pi\right)}{1-\exp\left(-\dfrac{2ij\pi}{N}\right)}=0&amp;lt;/tex&amp;gt;, так как &amp;lt;tex&amp;gt;e^{2\pi i}=1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Таким образом,  &lt;br /&gt;
&amp;lt;tex&amp;gt;\dfrac{1}{N}\sum\limits_{k=0}^{N-1}g\left(\phi_k\right)=\dfrac{1}{N}\sum\limits_{k=0}^{N-1}\left(a_0+g\left(\phi_k\right)\right)=a_0&amp;lt;/tex&amp;gt;, &lt;br /&gt;
а свободный член &amp;lt;tex&amp;gt;H\left(z\right)&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;L_6&amp;lt;/tex&amp;gt;, как известно из предыдущего раздела.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Производящая функция]]&lt;br /&gt;
&lt;br /&gt;
* [[Динамическое программирование]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.genfunc.ru/theory/lucky/ Задача о счастливых билетах :: Производящие функции]&lt;br /&gt;
&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 144с. ISBN 978-5-94057-042-4&lt;br /&gt;
[[Категория:Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория:Комбинаторика]]&lt;br /&gt;
[[Категория:Производящие функции]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63857</id>
		<title>Производящие функции нескольких переменных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63857"/>
				<updated>2018-03-01T14:52:50Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Многочлены Бернулли */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие функции нескольких переменных''' (англ. ''multivariable generating function'') {{---}} обычные [[Производящая функция | производящие функции]], зависящие более, чем от одной переменной. Очень часто применяются функции от двух переменных (далее они и будут рассматриваться), которые в общем случае принимают вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G(x, y) = \sum\limits_{n, k \geqslant 0} g_{n, k} x^n y^k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим несколько примеров : &lt;br /&gt;
&lt;br /&gt;
== Треугольник Паскаля ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Треугольник Паскаля''' (англ. ''Pascal's triangle'') {{---}} бесконечная таблица биномиальных коэффициентов&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D0%BD%D0%BE%D0%BC%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D1%8D%D1%84%D1%84%D0%B8%D1%86%D0%B8%D0%B5%D0%BD%D1%82 Биномиальные коэффициенты]&amp;lt;/ref&amp;gt;, имеющая треугольную форму. В этом треугольнике на вершине и по бокам стоят единицы. Каждое число равно сумме двух расположенных над ним чисел.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle.png|thumb|400px|right|Рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Элементы треугольника (рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;) перечисляют пути, идущие из его вершины в соответствующую клетку. Пути имеют вид ломаных, составленных из векторов единичной длины двух видов: идущих вправо-вниз и идущих влево-вниз.&lt;br /&gt;
&lt;br /&gt;
Производящая функция может быть сопоставлена треугольнику Паскаля несколькими способами. Например, можно рассмотреть производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,k = 0}^{\infty} c_{n,k} x^k y^n = \sum\limits_{n,k = 0}^{\infty} \begin{pmatrix} n \\ k \end{pmatrix} x^k y^n = \sum\limits_{n = 0}^{\infty}\Big(\sum\limits_{k = 0}^{n} \begin{pmatrix} n \\ k \end{pmatrix} x^k\Big) y^n = \sum\limits_{n = 0}^{\infty} (1 + x)^n y^n  = \dfrac{1}{1 - y - xy}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle_3.png|thumb|600px|right|Рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй способ соответсвует нумерации элементов треугольника числом отрезков каждого типа на путях, ведущих в соответствующую точку (рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;C_{n,m} = c_{n+m, n} = \begin{pmatrix} n + m \\ m \end{pmatrix}&amp;lt;/tex&amp;gt;. Тогда производящая функция будет иметь вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,m = 0}^{\infty} C_{n, m} x^n y^m = \sum\limits_{n,m = 0}^{\infty}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{k = 0}^{\infty} \sum\limits_{n + m = k}  \begin{pmatrix} n + m \\ n \end{pmatrix}&lt;br /&gt;
x^n y^m = \sum\limits_{k = 0}^{\infty} (x + y)^k = \dfrac{1}{1 -x - y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует еще один способ: сопоставить треугольнику Паскаля ''экспоненциальную производящую функцию''. Экспоненциальная производящая функция отличается от обычной тем, что в качестве коэффициентов степенного ряда берутся не элементы последовательности &amp;lt;tex&amp;gt;a_n&amp;lt;/tex&amp;gt;, а числа &amp;lt;tex&amp;gt;\dfrac{a_n}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Экспоненциальные производящие функции==&lt;br /&gt;
&lt;br /&gt;
Зафиксируем произвольную последовательность &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Каждой последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; мы можем сопоставить производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\{ \alpha_n \} \mapsto \sum\limits_{n = 0}^{\infty} a_n \alpha_n s^n&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
определяемую последовательностью &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Если в последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; отсутствуют нулевые элементы, то такое сопоставление взаимно однозначно. До сих пор мы пользовались обычными производящими функциями, отвечающими последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} \equiv 1&amp;lt;/tex&amp;gt;. В зависимости от преследуемых целей могут принести и другие последовательности. &lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие экспоненциальные функции''' (англ. ''exponential generating function'') {{---}} функции, соответсвующие последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} = \dfrac{1}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
Экспоненциальные производящие функции для целочисленных последовательностей называют '''функциями Гурвица''' (англ. ''Hurwitz function'').&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чем отличаются экспоненциальные производящие функции от обычных? Посмотрим на поведение экспоненциальных производящих функций при выполнении операции над ними. Сумма ведет себя обычным образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n = 0}^{\infty} \dfrac{a_n}{n!}s^n + \sum\limits_{n = 0}^{\infty} \dfrac{b+n}{n!}s^n = \sum\limits_{n = 0}^{\infty} \dfrac{(a_n + b_n)}{n!} s^n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а с произведением по-другому:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots\bigg)\bigg(\dfrac{b_0}{0!} + \dfrac{b_1}{1!}s + \dfrac{b_2}{2!}s^2 + \ldots\bigg) = \dfrac{a_0}{0!} \dfrac{b_0}{0!} + \bigg(\dfrac{a_0}{0!} \dfrac{b_1}{1!} + \dfrac{a_1}{1!} \dfrac{b_0}{0!}\bigg)s + \bigg(\dfrac{a_0}{0!} \dfrac{b_2}{2!} + \dfrac{a_1}{1!} \dfrac{b_1}{1!} + \dfrac{a_2}{2!} \dfrac{b_0}{0!}\bigg)s^2 + \ldots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициенты &amp;lt;tex&amp;gt;\dfrac{c_n}{n!}&amp;lt;/tex&amp;gt; произведения вычисляются по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;c_n = \begin{pmatrix} n \\ 0 \end{pmatrix} a_0 b_n + \begin{pmatrix} n \\ 1 \end{pmatrix} a_1 b_{n - 1} + \ldots + \begin{pmatrix} n \\ n \end{pmatrix} a_0 b_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Еще одно существенное отличие экспоненциальных производящих функций от обычных наблюдается при взятии производных и при интегрировании. Дифференцирование или интегрирование экспоненциальной производящей функции приводит к сдвигу последовательности ее коэффициентов без изменения их величины: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg( \dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg)^{'} = \dfrac{a_1}{0!} + \dfrac{a_2}{1!}s + \dfrac{a_3}{2!}s^2 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\int \bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg) = \dfrac{a_0}{1!}s + \dfrac{a_1}{2!}s^2 + \dfrac{a_2}{3!}s^3 + \dfrac{a_3}{4!}s^4 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обычная производящая функция &amp;lt;tex&amp;gt;A(s) = a_0 + a_1s + a_2s^2 + \ldots&amp;lt;/tex&amp;gt; выражается через экспоненциальную &amp;lt;tex&amp;gt;B(t) = \dfrac{a_0}{0!} + \dfrac{a_1}{1!}t + \dfrac{a_2}{2!}t^2 + \ldots &amp;lt;/tex&amp;gt; по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) = \int_{0}^{\infty} e^{-t} B(st) dt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Действительно, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k! = \int_{0}^{\infty} e^{-t}t^kdt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно выписать экспоненциальную производящую функцию для треугольника Паскаля:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n, m = 0}^{\infty} \dfrac{1}{(n + m)!}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{n = 0}^{\infty} \dfrac{(x + y)^n}{n!} = e^{x + y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Многочлены Бернулли==&lt;br /&gt;
Для начала введен операцию ''усреднения'', положив&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(f(x)) = \int\limits_{x}^{x+1}f(t)dt&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что эта операция переводит многочлены в многочлены: она линейна, т.е. &amp;lt;tex&amp;gt;A(a_1f_1 + a_2f_2) = a_1A(f_1) + a_2A(f_2)&amp;lt;/tex&amp;gt; для любых постоянных &amp;lt;tex&amp;gt;a_1, a_2&amp;lt;/tex&amp;gt; и любых многочленов &amp;lt;tex&amp;gt;f_1,&lt;br /&gt;
 f_2&amp;lt;/tex&amp;gt;, а ее значение на мономе&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%87%D0%BB%D0%B5%D0%BD Моном]&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt; равно&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(x^n) = ((x + 1)^{n+1} - x^{n+1}) / (n+1) = x^n + \ldots&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где многоточие обозначает слагаемые, степени которых меньше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Последняя формула показывает также, что преобразование &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; переводит пространство многочленов степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; в себя, а значит, является линейным оператором в этом пространстве. Этот оператор обратим. Действительно, любой многочлен степени не выше &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; может быть получен в результате усреднения многочлена такой же степени, и, используя последнюю формулу, мы заключаем, что и любой многочлен степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; является результатом усреднения некоторого многочлена степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Отметим, что при усреднении степень многочлена сохраняется.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Многочленом Бернулли''' (англ. ''Bernoulli polynomial'') степени &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; называется многочлен &amp;lt;tex&amp;gt;B_n(x)&amp;lt;/tex&amp;gt;, результатом усреднения которого служит моном &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt;, т.е. &amp;lt;tex&amp;gt;B_n(x) = A^{-1}(x^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Первые многочлены Бернулли нетрудно сосчитать:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_0(x) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_1(x) = x - \dfrac{1}{2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_2(x) = x^2 -x + \dfrac{1}{6}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_3(x) = x^3 - \dfrac{3}{2}x^2 + \dfrac{1}{2}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_4(x) = x^4 - 2x^3 + x^2 - \dfrac{1}{30}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_5(x) = x^5 - \dfrac{5}{2}x^4 + \dfrac{5}{3}x^3 - \dfrac{1}{6}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_6(x) = x^6 - 3x^5 + \dfrac{5}{2}x^4 - \dfrac{1}{2}x^2 + \dfrac{1}{42}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
| about = Экспоненциальная производящая функция для многочленов Бернулли&lt;br /&gt;
| statement = &lt;br /&gt;
Экспоненциальная производящая функция для многочленов Бернулли имеет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathcal{B}(x, s) = \sum\limits_{n=0}^{\infty}B_n(x)\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}e^{sx}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
| proof = &lt;br /&gt;
Для доказательства теоремы достаточно применить операцию усреднения к левой и правой частям равенства. С одной стороны, мы имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(B(x, s)) = \sum\limits_{n=0}^{\infty}A(B_n(x))\dfrac{s^n}{n!} = \sum\limits_{n=0}^{\infty}x^n\dfrac{s^n}{n!} = e^{xs}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С другой стороны, имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(\dfrac{s}{e^s - 1}e^{sx}) = \dfrac{s}{e^s-1}A(e^{sx}) = \dfrac{s}{e^s-1}\dfrac{1}{s}(e^{s(x+1)} - e^{sx}) = e^{sx}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
и теорема доказана.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Определим теперь ''числа Бернулли''&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%91%D0%B5%D1%80%D0%BD%D1%83%D0%BB%D0%BB%D0%B8 числа Бернулли]&amp;lt;/ref&amp;gt; как значения многочленов Бернулли в нуле. Вот начало последовательности чисел Бернулли:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;1, -\dfrac{1}{2}, 0, \dfrac{1}{6}, -\dfrac{1}{30}, \dfrac{1}{42}, 0, -\dfrac{1}{30}, \dfrac{5}{66}, 0, -\dfrac{691}{2730}, 0, \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Доказанная теорема позволяет нам легко выписать экспоненциальную производящую функцию для чисел Бернулли. Для этого достаточно подставить в экспоненциальную производящую функцию для многочленов Бернулли значение &amp;lt;tex&amp;gt;x = 0&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n=0} B_n\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 57с. ISBN 978-5-94057-042-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Производящая функция]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63856</id>
		<title>Производящие функции нескольких переменных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63856"/>
				<updated>2018-03-01T14:40:25Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Экспоненциальные производящие функции */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие функции нескольких переменных''' (англ. ''multivariable generating function'') {{---}} обычные [[Производящая функция | производящие функции]], зависящие более, чем от одной переменной. Очень часто применяются функции от двух переменных (далее они и будут рассматриваться), которые в общем случае принимают вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G(x, y) = \sum\limits_{n, k \geqslant 0} g_{n, k} x^n y^k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим несколько примеров : &lt;br /&gt;
&lt;br /&gt;
== Треугольник Паскаля ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Треугольник Паскаля''' (англ. ''Pascal's triangle'') {{---}} бесконечная таблица биномиальных коэффициентов&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D0%BD%D0%BE%D0%BC%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D1%8D%D1%84%D1%84%D0%B8%D1%86%D0%B8%D0%B5%D0%BD%D1%82 Биномиальные коэффициенты]&amp;lt;/ref&amp;gt;, имеющая треугольную форму. В этом треугольнике на вершине и по бокам стоят единицы. Каждое число равно сумме двух расположенных над ним чисел.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle.png|thumb|400px|right|Рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Элементы треугольника (рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;) перечисляют пути, идущие из его вершины в соответствующую клетку. Пути имеют вид ломаных, составленных из векторов единичной длины двух видов: идущих вправо-вниз и идущих влево-вниз.&lt;br /&gt;
&lt;br /&gt;
Производящая функция может быть сопоставлена треугольнику Паскаля несколькими способами. Например, можно рассмотреть производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,k = 0}^{\infty} c_{n,k} x^k y^n = \sum\limits_{n,k = 0}^{\infty} \begin{pmatrix} n \\ k \end{pmatrix} x^k y^n = \sum\limits_{n = 0}^{\infty}\Big(\sum\limits_{k = 0}^{n} \begin{pmatrix} n \\ k \end{pmatrix} x^k\Big) y^n = \sum\limits_{n = 0}^{\infty} (1 + x)^n y^n  = \dfrac{1}{1 - y - xy}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle_3.png|thumb|600px|right|Рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй способ соответсвует нумерации элементов треугольника числом отрезков каждого типа на путях, ведущих в соответствующую точку (рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;C_{n,m} = c_{n+m, n} = \begin{pmatrix} n + m \\ m \end{pmatrix}&amp;lt;/tex&amp;gt;. Тогда производящая функция будет иметь вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,m = 0}^{\infty} C_{n, m} x^n y^m = \sum\limits_{n,m = 0}^{\infty}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{k = 0}^{\infty} \sum\limits_{n + m = k}  \begin{pmatrix} n + m \\ n \end{pmatrix}&lt;br /&gt;
x^n y^m = \sum\limits_{k = 0}^{\infty} (x + y)^k = \dfrac{1}{1 -x - y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует еще один способ: сопоставить треугольнику Паскаля ''экспоненциальную производящую функцию''. Экспоненциальная производящая функция отличается от обычной тем, что в качестве коэффициентов степенного ряда берутся не элементы последовательности &amp;lt;tex&amp;gt;a_n&amp;lt;/tex&amp;gt;, а числа &amp;lt;tex&amp;gt;\dfrac{a_n}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Экспоненциальные производящие функции==&lt;br /&gt;
&lt;br /&gt;
Зафиксируем произвольную последовательность &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Каждой последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; мы можем сопоставить производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\{ \alpha_n \} \mapsto \sum\limits_{n = 0}^{\infty} a_n \alpha_n s^n&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
определяемую последовательностью &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Если в последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; отсутствуют нулевые элементы, то такое сопоставление взаимно однозначно. До сих пор мы пользовались обычными производящими функциями, отвечающими последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} \equiv 1&amp;lt;/tex&amp;gt;. В зависимости от преследуемых целей могут принести и другие последовательности. &lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие экспоненциальные функции''' (англ. ''exponential generating function'') {{---}} функции, соответсвующие последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} = \dfrac{1}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
Экспоненциальные производящие функции для целочисленных последовательностей называют '''функциями Гурвица''' (англ. ''Hurwitz function'').&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чем отличаются экспоненциальные производящие функции от обычных? Посмотрим на поведение экспоненциальных производящих функций при выполнении операции над ними. Сумма ведет себя обычным образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n = 0}^{\infty} \dfrac{a_n}{n!}s^n + \sum\limits_{n = 0}^{\infty} \dfrac{b+n}{n!}s^n = \sum\limits_{n = 0}^{\infty} \dfrac{(a_n + b_n)}{n!} s^n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а с произведением по-другому:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots\bigg)\bigg(\dfrac{b_0}{0!} + \dfrac{b_1}{1!}s + \dfrac{b_2}{2!}s^2 + \ldots\bigg) = \dfrac{a_0}{0!} \dfrac{b_0}{0!} + \bigg(\dfrac{a_0}{0!} \dfrac{b_1}{1!} + \dfrac{a_1}{1!} \dfrac{b_0}{0!}\bigg)s + \bigg(\dfrac{a_0}{0!} \dfrac{b_2}{2!} + \dfrac{a_1}{1!} \dfrac{b_1}{1!} + \dfrac{a_2}{2!} \dfrac{b_0}{0!}\bigg)s^2 + \ldots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициенты &amp;lt;tex&amp;gt;\dfrac{c_n}{n!}&amp;lt;/tex&amp;gt; произведения вычисляются по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;c_n = \begin{pmatrix} n \\ 0 \end{pmatrix} a_0 b_n + \begin{pmatrix} n \\ 1 \end{pmatrix} a_1 b_{n - 1} + \ldots + \begin{pmatrix} n \\ n \end{pmatrix} a_0 b_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Еще одно существенное отличие экспоненциальных производящих функций от обычных наблюдается при взятии производных и при интегрировании. Дифференцирование или интегрирование экспоненциальной производящей функции приводит к сдвигу последовательности ее коэффициентов без изменения их величины: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg( \dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg)^{'} = \dfrac{a_1}{0!} + \dfrac{a_2}{1!}s + \dfrac{a_3}{2!}s^2 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\int \bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg) = \dfrac{a_0}{1!}s + \dfrac{a_1}{2!}s^2 + \dfrac{a_2}{3!}s^3 + \dfrac{a_3}{4!}s^4 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обычная производящая функция &amp;lt;tex&amp;gt;A(s) = a_0 + a_1s + a_2s^2 + \ldots&amp;lt;/tex&amp;gt; выражается через экспоненциальную &amp;lt;tex&amp;gt;B(t) = \dfrac{a_0}{0!} + \dfrac{a_1}{1!}t + \dfrac{a_2}{2!}t^2 + \ldots &amp;lt;/tex&amp;gt; по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) = \int_{0}^{\infty} e^{-t} B(st) dt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Действительно, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k! = \int_{0}^{\infty} e^{-t}t^kdt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно выписать экспоненциальную производящую функцию для треугольника Паскаля:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n, m = 0}^{\infty} \dfrac{1}{(n + m)!}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{n = 0}^{\infty} \dfrac{(x + y)^n}{n!} = e^{x + y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Многочлены Бернулли==&lt;br /&gt;
Для начала введен операцию ''усреднения'', положив&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(f(x)) = \int_{x}^{x+1}f(t)dt&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что эта операция переводит многочлены в многочлены: она линейна, т.е. &amp;lt;tex&amp;gt;A(a_1f_1 + a_2f_2) = a_1A(f_1) + a_2A(f_2)&amp;lt;/tex&amp;gt; для любых постоянных &amp;lt;tex&amp;gt;a_1, a_2&amp;lt;/tex&amp;gt; и любых многочленов &amp;lt;tex&amp;gt;f_1,&lt;br /&gt;
 f_2&amp;lt;/tex&amp;gt;, а ее значение на мономе&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%87%D0%BB%D0%B5%D0%BD Моном]&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt; равно&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(x^n) = ((x + 1)^{n+1} - x^{n+1}) / (n+1) = x^n + \ldots&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где многоточие обозначает слагаемые, степени которых меньше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Последняя формула показывает также, что преобразование &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; переводит пространство многочленов степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; в себя, а значит, является линейным оператором в этом пространстве. Этот оператор обратим. Действительно, любой многочлен степени не выше &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; может быть получен в результате усреднения многочлена такой же степени, и, используя последнюю формулу, мы заключаем, что и любой многочлен степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; является результатом усреднения некоторого многочлена степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Отметим, что при усреднении степень многочлена сохраняется.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Многочленом Бернулли''' (англ. ''Bernoulli polynomial'') степени &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; называется многочлен &amp;lt;tex&amp;gt;B_n(x)&amp;lt;/tex&amp;gt;, результатом усреднения которого служит моном &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt;, т.е. &amp;lt;tex&amp;gt;B_n(x) = A^{-1}(x^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Первые многочлены Бернулли нетрудно сосчитать:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_0(x) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_1(x) = x - \dfrac{1}{2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_2(x) = x^2 -x + \dfrac{1}{6}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_3(x) = x^3 - \dfrac{3}{2}x^2 + \dfrac{1}{2}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_4(x) = x^4 - 2x^3 + x^2 - \dfrac{1}{30}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_5(x) = x^5 - \dfrac{5}{2}x^4 + \dfrac{5}{3}x^3 - \dfrac{1}{6}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_6(x) = x^6 - 3x^5 + \dfrac{5}{2}x^4 - \dfrac{1}{2}x^2 + \dfrac{1}{42}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
| about = Экспоненциальная производящая функция для многочленов Бернулли&lt;br /&gt;
| statement = &lt;br /&gt;
Экспоненциальная производящая функция для многочленов Бернулли имеет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathcal{B}(x, s) = \sum\limits_{n=0}^{\infty}B_n(x)\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}e^{sx}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
| proof = &lt;br /&gt;
Для доказательства теоремы достаточно применить операцию усреднения к левой и правой частям равенства. С одной стороны, мы имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(B(x, s)) = \sum\limits_{n=0}^{\infty}A(B_n(x))\dfrac{s^n}{n!} = \sum\limits_{n=0}^{\infty}x^n\dfrac{s^n}{n!} = e^{xs}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С другой стороны, имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(\dfrac{s}{e^s - 1}e^{sx}) = \dfrac{s}{e^s-1}A(e^{sx}) = \dfrac{s}{e^s-1}\dfrac{1}{s}(e^{s(x+1)} - e^{sx}) = e^{sx}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
и теорема доказана.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Определим теперь ''числа Бернулли''&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%91%D0%B5%D1%80%D0%BD%D1%83%D0%BB%D0%BB%D0%B8 числа Бернулли]&amp;lt;/ref&amp;gt; как значения многочленов Бернулли в нуле. Вот начало последовательности чисел Бернулли:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;1, -\dfrac{1}{2}, 0, \dfrac{1}{6}, -\dfrac{1}{30}, \dfrac{1}{42}, 0, -\dfrac{1}{30}, \dfrac{5}{66}, 0, -\dfrac{691}{2730}, 0, \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Доказанная теорема позволяет нам легко выписать экспоненциальную производящую функцию для чисел Бернулли. Для этого достаточно подставить в экспоненциальную производящую функцию для многочленов Бернулли значение &amp;lt;tex&amp;gt;x = 0&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n=0} B_n\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 57с. ISBN 978-5-94057-042-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Производящая функция]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63855</id>
		<title>Производящие функции нескольких переменных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63855"/>
				<updated>2018-03-01T14:39:49Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Экспоненциальные производящие функции */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие функции нескольких переменных''' (англ. ''multivariable generating function'') {{---}} обычные [[Производящая функция | производящие функции]], зависящие более, чем от одной переменной. Очень часто применяются функции от двух переменных (далее они и будут рассматриваться), которые в общем случае принимают вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G(x, y) = \sum\limits_{n, k \geqslant 0} g_{n, k} x^n y^k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим несколько примеров : &lt;br /&gt;
&lt;br /&gt;
== Треугольник Паскаля ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Треугольник Паскаля''' (англ. ''Pascal's triangle'') {{---}} бесконечная таблица биномиальных коэффициентов&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D0%BD%D0%BE%D0%BC%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D1%8D%D1%84%D1%84%D0%B8%D1%86%D0%B8%D0%B5%D0%BD%D1%82 Биномиальные коэффициенты]&amp;lt;/ref&amp;gt;, имеющая треугольную форму. В этом треугольнике на вершине и по бокам стоят единицы. Каждое число равно сумме двух расположенных над ним чисел.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle.png|thumb|400px|right|Рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Элементы треугольника (рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;) перечисляют пути, идущие из его вершины в соответствующую клетку. Пути имеют вид ломаных, составленных из векторов единичной длины двух видов: идущих вправо-вниз и идущих влево-вниз.&lt;br /&gt;
&lt;br /&gt;
Производящая функция может быть сопоставлена треугольнику Паскаля несколькими способами. Например, можно рассмотреть производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,k = 0}^{\infty} c_{n,k} x^k y^n = \sum\limits_{n,k = 0}^{\infty} \begin{pmatrix} n \\ k \end{pmatrix} x^k y^n = \sum\limits_{n = 0}^{\infty}\Big(\sum\limits_{k = 0}^{n} \begin{pmatrix} n \\ k \end{pmatrix} x^k\Big) y^n = \sum\limits_{n = 0}^{\infty} (1 + x)^n y^n  = \dfrac{1}{1 - y - xy}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle_3.png|thumb|600px|right|Рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй способ соответсвует нумерации элементов треугольника числом отрезков каждого типа на путях, ведущих в соответствующую точку (рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;C_{n,m} = c_{n+m, n} = \begin{pmatrix} n + m \\ m \end{pmatrix}&amp;lt;/tex&amp;gt;. Тогда производящая функция будет иметь вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,m = 0}^{\infty} C_{n, m} x^n y^m = \sum\limits_{n,m = 0}^{\infty}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{k = 0}^{\infty} \sum\limits_{n + m = k}  \begin{pmatrix} n + m \\ n \end{pmatrix}&lt;br /&gt;
x^n y^m = \sum\limits_{k = 0}^{\infty} (x + y)^k = \dfrac{1}{1 -x - y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует еще один способ: сопоставить треугольнику Паскаля ''экспоненциальную производящую функцию''. Экспоненциальная производящая функция отличается от обычной тем, что в качестве коэффициентов степенного ряда берутся не элементы последовательности &amp;lt;tex&amp;gt;a_n&amp;lt;/tex&amp;gt;, а числа &amp;lt;tex&amp;gt;\dfrac{a_n}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Экспоненциальные производящие функции==&lt;br /&gt;
&lt;br /&gt;
Зафиксируем произвольную последовательность &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Каждой последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; мы можем сопоставить производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\{ \alpha_n \} \mapsto \sum\limits_{n = 0}^{\infty} a_n \alpha_n s^n&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
определяемую последовательностью &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Если в последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; отсутствуют нулевые элементы, то такое сопоставление взаимно однозначно. До сих пор мы пользовались обычными производящими функциями, отвечающими последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} \equiv 1&amp;lt;/tex&amp;gt;. В зависимости от преследуемых целей могут принести и другие последовательности. &lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие экспоненциальные функции''' (англ. ''exponential generating function'') {{---}} функции, соответсвующие последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} = \dfrac{1}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
Экспоненциальные производящие функции для целочисленных последовательностей называют '''функциями Гурвица''' (англ. ''Hurwitz function'').&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чем отличаются экспоненциальные производящие функции от обычных? Посмотрим на поведение экспоненциальных производящих функций при выполнении операции над ними. Сумма ведет себя обычным образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n = 0}^{\infty} \dfrac{a_n}{n!}s^n + \sum\limits_{n = 0}^{\infty} \dfrac{b+n}{n!}s^n = \sum\limits_{n = 0}^{\infty} \dfrac{(a_n + b_n)}{n!} s^n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а с произведением по-другому :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots\bigg)\bigg(\dfrac{b_0}{0!} + \dfrac{b_1}{1!}s + \dfrac{b_2}{2!}s^2 + \ldots\bigg) = \dfrac{a_0}{0!} \dfrac{b_0}{0!} + \bigg(\dfrac{a_0}{0!} \dfrac{b_1}{1!} + \dfrac{a_1}{1!} \dfrac{b_0}{0!}\bigg)s + \bigg(\dfrac{a_0}{0!} \dfrac{b_2}{2!} + \dfrac{a_1}{1!} \dfrac{b_1}{1!} + \dfrac{a_2}{2!} \dfrac{b_0}{0!}\bigg)s^2 + \ldots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициенты &amp;lt;tex&amp;gt;\dfrac{c_n}{n!}&amp;lt;/tex&amp;gt; произведения вычисляются по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;c_n = \begin{pmatrix} n \\ 0 \end{pmatrix} a_0 b_n + \begin{pmatrix} n \\ 1 \end{pmatrix} a_1 b_{n - 1} + \ldots + \begin{pmatrix} n \\ n \end{pmatrix} a_0 b_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Еще одно существенное отличие экспоненциальных производящих функций от обычных наблюдается при взятии производных и при интегрировании. Дифференцирование или интегрирование экспоненциальной производящей функции приводит к сдвигу последовательности ее коэффициентов без изменения их величины: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg( \dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg)^{'} = \dfrac{a_1}{0!} + \dfrac{a_2}{1!}s + \dfrac{a_3}{2!}s^2 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\int \bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg) = \dfrac{a_0}{1!}s + \dfrac{a_1}{2!}s^2 + \dfrac{a_2}{3!}s^3 + \dfrac{a_3}{4!}s^4 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обычная производящая функция &amp;lt;tex&amp;gt;A(s) = a_0 + a_1s + a_2s^2 + \ldots&amp;lt;/tex&amp;gt; выражается через экспоненциальную &amp;lt;tex&amp;gt;B(t) = \dfrac{a_0}{0!} + \dfrac{a_1}{1!}t + \dfrac{a_2}{2!}t^2 + \ldots &amp;lt;/tex&amp;gt; по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) = \int_{0}^{\infty} e^{-t} B(st) dt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Действительно, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k! = \int_{0}^{\infty} e^{-t}t^kdt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно выписать экспоненциальную производящую функцию для треугольника Паскаля:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n, m = 0}^{\infty} \dfrac{1}{(n + m)!}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{n = 0}^{\infty} \dfrac{(x + y)^n}{n!} = e^{x + y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Многочлены Бернулли==&lt;br /&gt;
Для начала введен операцию ''усреднения'', положив&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(f(x)) = \int_{x}^{x+1}f(t)dt&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что эта операция переводит многочлены в многочлены: она линейна, т.е. &amp;lt;tex&amp;gt;A(a_1f_1 + a_2f_2) = a_1A(f_1) + a_2A(f_2)&amp;lt;/tex&amp;gt; для любых постоянных &amp;lt;tex&amp;gt;a_1, a_2&amp;lt;/tex&amp;gt; и любых многочленов &amp;lt;tex&amp;gt;f_1,&lt;br /&gt;
 f_2&amp;lt;/tex&amp;gt;, а ее значение на мономе&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%87%D0%BB%D0%B5%D0%BD Моном]&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt; равно&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(x^n) = ((x + 1)^{n+1} - x^{n+1}) / (n+1) = x^n + \ldots&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где многоточие обозначает слагаемые, степени которых меньше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Последняя формула показывает также, что преобразование &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; переводит пространство многочленов степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; в себя, а значит, является линейным оператором в этом пространстве. Этот оператор обратим. Действительно, любой многочлен степени не выше &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; может быть получен в результате усреднения многочлена такой же степени, и, используя последнюю формулу, мы заключаем, что и любой многочлен степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; является результатом усреднения некоторого многочлена степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Отметим, что при усреднении степень многочлена сохраняется.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Многочленом Бернулли''' (англ. ''Bernoulli polynomial'') степени &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; называется многочлен &amp;lt;tex&amp;gt;B_n(x)&amp;lt;/tex&amp;gt;, результатом усреднения которого служит моном &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt;, т.е. &amp;lt;tex&amp;gt;B_n(x) = A^{-1}(x^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Первые многочлены Бернулли нетрудно сосчитать:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_0(x) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_1(x) = x - \dfrac{1}{2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_2(x) = x^2 -x + \dfrac{1}{6}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_3(x) = x^3 - \dfrac{3}{2}x^2 + \dfrac{1}{2}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_4(x) = x^4 - 2x^3 + x^2 - \dfrac{1}{30}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_5(x) = x^5 - \dfrac{5}{2}x^4 + \dfrac{5}{3}x^3 - \dfrac{1}{6}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_6(x) = x^6 - 3x^5 + \dfrac{5}{2}x^4 - \dfrac{1}{2}x^2 + \dfrac{1}{42}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
| about = Экспоненциальная производящая функция для многочленов Бернулли&lt;br /&gt;
| statement = &lt;br /&gt;
Экспоненциальная производящая функция для многочленов Бернулли имеет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathcal{B}(x, s) = \sum\limits_{n=0}^{\infty}B_n(x)\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}e^{sx}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
| proof = &lt;br /&gt;
Для доказательства теоремы достаточно применить операцию усреднения к левой и правой частям равенства. С одной стороны, мы имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(B(x, s)) = \sum\limits_{n=0}^{\infty}A(B_n(x))\dfrac{s^n}{n!} = \sum\limits_{n=0}^{\infty}x^n\dfrac{s^n}{n!} = e^{xs}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С другой стороны, имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(\dfrac{s}{e^s - 1}e^{sx}) = \dfrac{s}{e^s-1}A(e^{sx}) = \dfrac{s}{e^s-1}\dfrac{1}{s}(e^{s(x+1)} - e^{sx}) = e^{sx}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
и теорема доказана.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Определим теперь ''числа Бернулли''&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%91%D0%B5%D1%80%D0%BD%D1%83%D0%BB%D0%BB%D0%B8 числа Бернулли]&amp;lt;/ref&amp;gt; как значения многочленов Бернулли в нуле. Вот начало последовательности чисел Бернулли:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;1, -\dfrac{1}{2}, 0, \dfrac{1}{6}, -\dfrac{1}{30}, \dfrac{1}{42}, 0, -\dfrac{1}{30}, \dfrac{5}{66}, 0, -\dfrac{691}{2730}, 0, \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Доказанная теорема позволяет нам легко выписать экспоненциальную производящую функцию для чисел Бернулли. Для этого достаточно подставить в экспоненциальную производящую функцию для многочленов Бернулли значение &amp;lt;tex&amp;gt;x = 0&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n=0} B_n\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 57с. ISBN 978-5-94057-042-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Производящая функция]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63854</id>
		<title>Производящие функции нескольких переменных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63854"/>
				<updated>2018-03-01T14:37:07Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Экспоненциальные производящие функции */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие функции нескольких переменных''' (англ. ''multivariable generating function'') {{---}} обычные [[Производящая функция | производящие функции]], зависящие более, чем от одной переменной. Очень часто применяются функции от двух переменных (далее они и будут рассматриваться), которые в общем случае принимают вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G(x, y) = \sum\limits_{n, k \geqslant 0} g_{n, k} x^n y^k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим несколько примеров : &lt;br /&gt;
&lt;br /&gt;
== Треугольник Паскаля ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Треугольник Паскаля''' (англ. ''Pascal's triangle'') {{---}} бесконечная таблица биномиальных коэффициентов&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D0%BD%D0%BE%D0%BC%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D1%8D%D1%84%D1%84%D0%B8%D1%86%D0%B8%D0%B5%D0%BD%D1%82 Биномиальные коэффициенты]&amp;lt;/ref&amp;gt;, имеющая треугольную форму. В этом треугольнике на вершине и по бокам стоят единицы. Каждое число равно сумме двух расположенных над ним чисел.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle.png|thumb|400px|right|Рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Элементы треугольника (рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;) перечисляют пути, идущие из его вершины в соответствующую клетку. Пути имеют вид ломаных, составленных из векторов единичной длины двух видов: идущих вправо-вниз и идущих влево-вниз.&lt;br /&gt;
&lt;br /&gt;
Производящая функция может быть сопоставлена треугольнику Паскаля несколькими способами. Например, можно рассмотреть производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,k = 0}^{\infty} c_{n,k} x^k y^n = \sum\limits_{n,k = 0}^{\infty} \begin{pmatrix} n \\ k \end{pmatrix} x^k y^n = \sum\limits_{n = 0}^{\infty}\Big(\sum\limits_{k = 0}^{n} \begin{pmatrix} n \\ k \end{pmatrix} x^k\Big) y^n = \sum\limits_{n = 0}^{\infty} (1 + x)^n y^n  = \dfrac{1}{1 - y - xy}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle_3.png|thumb|600px|right|Рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй способ соответсвует нумерации элементов треугольника числом отрезков каждого типа на путях, ведущих в соответствующую точку (рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;C_{n,m} = c_{n+m, n} = \begin{pmatrix} n + m \\ m \end{pmatrix}&amp;lt;/tex&amp;gt;. Тогда производящая функция будет иметь вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,m = 0}^{\infty} C_{n, m} x^n y^m = \sum\limits_{n,m = 0}^{\infty}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{k = 0}^{\infty} \sum\limits_{n + m = k}  \begin{pmatrix} n + m \\ n \end{pmatrix}&lt;br /&gt;
x^n y^m = \sum\limits_{k = 0}^{\infty} (x + y)^k = \dfrac{1}{1 -x - y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует еще один способ: сопоставить треугольнику Паскаля ''экспоненциальную производящую функцию''. Экспоненциальная производящая функция отличается от обычной тем, что в качестве коэффициентов степенного ряда берутся не элементы последовательности &amp;lt;tex&amp;gt;a_n&amp;lt;/tex&amp;gt;, а числа &amp;lt;tex&amp;gt;\dfrac{a_n}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Экспоненциальные производящие функции==&lt;br /&gt;
&lt;br /&gt;
Зафиксируем произвольную последовательность &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Каждой последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; мы можем сопоставить производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\{ \alpha_n \} \mapsto \sum\limits_{n = 0}^{\infty} a_n \alpha_n s^n&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
определяемую последовательностью &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Если в последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; отсутствуют нулевые элементы, то такое сопоставление взаимно однозначно. До сих пор мы пользовались обычными производящими функциями, отвечающими последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} \equiv 1&amp;lt;/tex&amp;gt;. В зависимости от преследуемых целей могут принести и другие последовательности. &lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие экспоненциальные функции''' (англ. ''exponential generating function'') {{---}} функции, соответсвующие последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} = \dfrac{1}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
Экспоненциальные производящие функции для целочисленных последовательностей называют '''функциями Гурвица''' (англ. ''Hurwitz function'').&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чем отличаются экспоненциальные производящие функции от обычных? Посмотрим на поведение экспоненциальных производящих функций при выполнении операции над ними. Сумма ведет себя обычным образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n = 0}^{\infty} \dfrac{a_n}{n!}s^n + \sum\limits_{n = 0}^{\infty} \dfrac{b+n}{n!}s^n = \sum\limits_{n = 0}^{\infty} \dfrac{(a_n + b_n)}{n!} s^n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а с произведением по-другому :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots\bigg)\bigg(\dfrac{b_0}{0!} + \dfrac{b_1}{1!}s + \dfrac{b_2}{2!}s^2 + \ldots\bigg) = \dfrac{a_0}{0!} \dfrac{b_0}{0!} + \bigg(\dfrac{a_0}{0!} \dfrac{b_1}{1!} + \dfrac{a_1}{1!} \dfrac{b_0}{0!}\bigg)s + \bigg(\dfrac{a_0}{0!} \dfrac{b_2}{2!} + \dfrac{a_1}{1!} \dfrac{b_1}{1!} + \dfrac{a_2}{2!} \dfrac{b_0}{0!}\bigg)s^2 + \ldots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициенты &amp;lt;tex&amp;gt;\dfrac{c_n}{n!}&amp;lt;/tex&amp;gt; произведения вычисляются по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;c_n = \begin{pmatrix} n \\ 0 \end{pmatrix} a_0 b_n + \begin{pmatrix} n \\ 1 \end{pmatrix} a_1 b_{n - 1} + \ldots + \begin{pmatrix} n \\ n \end{pmatrix} a_0 b_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Еще одно существенное отличие экспоненциальных производящих функций от обычных наблюдается при взятии производных (и интегрировании). Дифференцирование или интегрирование экспоненциальной производящей функции приводит к сдвигу последовательности ее коэффициентов без изменения их велечины: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg( \dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg)^{'} = \dfrac{a_1}{0!} + \dfrac{a_2}{1!}s + \dfrac{a_3}{2!}s^2 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\int \bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg) = \dfrac{a_0}{1!}s + \dfrac{a_1}{2!}s^2 + \dfrac{a_2}{3!}s^3 + \dfrac{a_3}{4!}s^4 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обычная производящая функция &amp;lt;tex&amp;gt;A(s) = a_0 + a_1s + a_2s^2 + \ldots&amp;lt;/tex&amp;gt; выражается через экспоненциальную &amp;lt;tex&amp;gt;B(t) = \dfrac{a_0}{0!} + \dfrac{a_1}{1!}t + \dfrac{a_2}{2!}t^2 + \ldots &amp;lt;/tex&amp;gt; по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) = \int_{0}^{\infty} e^{-t} B(st) dt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Действительно, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k! = \int_{0}^{\infty} e^{-t}t^kdt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно выписать экспоненциальную производящую функцию для треугольника Паскаля:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n, m = 0}^{\infty} \dfrac{1}{(n + m)!}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{n = 0}^{\infty} \dfrac{(x + y)^n}{n!} = e^{x + y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Многочлены Бернулли==&lt;br /&gt;
Для начала введен операцию ''усреднения'', положив&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(f(x)) = \int_{x}^{x+1}f(t)dt&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что эта операция переводит многочлены в многочлены: она линейна, т.е. &amp;lt;tex&amp;gt;A(a_1f_1 + a_2f_2) = a_1A(f_1) + a_2A(f_2)&amp;lt;/tex&amp;gt; для любых постоянных &amp;lt;tex&amp;gt;a_1, a_2&amp;lt;/tex&amp;gt; и любых многочленов &amp;lt;tex&amp;gt;f_1,&lt;br /&gt;
 f_2&amp;lt;/tex&amp;gt;, а ее значение на мономе&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%87%D0%BB%D0%B5%D0%BD Моном]&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt; равно&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(x^n) = ((x + 1)^{n+1} - x^{n+1}) / (n+1) = x^n + \ldots&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где многоточие обозначает слагаемые, степени которых меньше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Последняя формула показывает также, что преобразование &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; переводит пространство многочленов степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; в себя, а значит, является линейным оператором в этом пространстве. Этот оператор обратим. Действительно, любой многочлен степени не выше &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; может быть получен в результате усреднения многочлена такой же степени, и, используя последнюю формулу, мы заключаем, что и любой многочлен степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; является результатом усреднения некоторого многочлена степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Отметим, что при усреднении степень многочлена сохраняется.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Многочленом Бернулли''' (англ. ''Bernoulli polynomial'') степени &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; называется многочлен &amp;lt;tex&amp;gt;B_n(x)&amp;lt;/tex&amp;gt;, результатом усреднения которого служит моном &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt;, т.е. &amp;lt;tex&amp;gt;B_n(x) = A^{-1}(x^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Первые многочлены Бернулли нетрудно сосчитать:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_0(x) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_1(x) = x - \dfrac{1}{2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_2(x) = x^2 -x + \dfrac{1}{6}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_3(x) = x^3 - \dfrac{3}{2}x^2 + \dfrac{1}{2}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_4(x) = x^4 - 2x^3 + x^2 - \dfrac{1}{30}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_5(x) = x^5 - \dfrac{5}{2}x^4 + \dfrac{5}{3}x^3 - \dfrac{1}{6}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_6(x) = x^6 - 3x^5 + \dfrac{5}{2}x^4 - \dfrac{1}{2}x^2 + \dfrac{1}{42}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
| about = Экспоненциальная производящая функция для многочленов Бернулли&lt;br /&gt;
| statement = &lt;br /&gt;
Экспоненциальная производящая функция для многочленов Бернулли имеет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathcal{B}(x, s) = \sum\limits_{n=0}^{\infty}B_n(x)\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}e^{sx}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
| proof = &lt;br /&gt;
Для доказательства теоремы достаточно применить операцию усреднения к левой и правой частям равенства. С одной стороны, мы имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(B(x, s)) = \sum\limits_{n=0}^{\infty}A(B_n(x))\dfrac{s^n}{n!} = \sum\limits_{n=0}^{\infty}x^n\dfrac{s^n}{n!} = e^{xs}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С другой стороны, имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(\dfrac{s}{e^s - 1}e^{sx}) = \dfrac{s}{e^s-1}A(e^{sx}) = \dfrac{s}{e^s-1}\dfrac{1}{s}(e^{s(x+1)} - e^{sx}) = e^{sx}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
и теорема доказана.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Определим теперь ''числа Бернулли''&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%91%D0%B5%D1%80%D0%BD%D1%83%D0%BB%D0%BB%D0%B8 числа Бернулли]&amp;lt;/ref&amp;gt; как значения многочленов Бернулли в нуле. Вот начало последовательности чисел Бернулли:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;1, -\dfrac{1}{2}, 0, \dfrac{1}{6}, -\dfrac{1}{30}, \dfrac{1}{42}, 0, -\dfrac{1}{30}, \dfrac{5}{66}, 0, -\dfrac{691}{2730}, 0, \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Доказанная теорема позволяет нам легко выписать экспоненциальную производящую функцию для чисел Бернулли. Для этого достаточно подставить в экспоненциальную производящую функцию для многочленов Бернулли значение &amp;lt;tex&amp;gt;x = 0&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n=0} B_n\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 57с. ISBN 978-5-94057-042-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Производящая функция]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63853</id>
		<title>Производящие функции нескольких переменных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=63853"/>
				<updated>2018-03-01T14:33:20Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие функции нескольких переменных''' (англ. ''multivariable generating function'') {{---}} обычные [[Производящая функция | производящие функции]], зависящие более, чем от одной переменной. Очень часто применяются функции от двух переменных (далее они и будут рассматриваться), которые в общем случае принимают вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G(x, y) = \sum\limits_{n, k \geqslant 0} g_{n, k} x^n y^k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим несколько примеров : &lt;br /&gt;
&lt;br /&gt;
== Треугольник Паскаля ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Треугольник Паскаля''' (англ. ''Pascal's triangle'') {{---}} бесконечная таблица биномиальных коэффициентов&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D0%BD%D0%BE%D0%BC%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D1%8D%D1%84%D1%84%D0%B8%D1%86%D0%B8%D0%B5%D0%BD%D1%82 Биномиальные коэффициенты]&amp;lt;/ref&amp;gt;, имеющая треугольную форму. В этом треугольнике на вершине и по бокам стоят единицы. Каждое число равно сумме двух расположенных над ним чисел.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle.png|thumb|400px|right|Рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Элементы треугольника (рис.&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;) перечисляют пути, идущие из его вершины в соответствующую клетку. Пути имеют вид ломаных, составленных из векторов единичной длины двух видов: идущих вправо-вниз и идущих влево-вниз.&lt;br /&gt;
&lt;br /&gt;
Производящая функция может быть сопоставлена треугольнику Паскаля несколькими способами. Например, можно рассмотреть производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,k = 0}^{\infty} c_{n,k} x^k y^n = \sum\limits_{n,k = 0}^{\infty} \begin{pmatrix} n \\ k \end{pmatrix} x^k y^n = \sum\limits_{n = 0}^{\infty}\Big(\sum\limits_{k = 0}^{n} \begin{pmatrix} n \\ k \end{pmatrix} x^k\Big) y^n = \sum\limits_{n = 0}^{\infty} (1 + x)^n y^n  = \dfrac{1}{1 - y - xy}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pascal_triangle_3.png|thumb|600px|right|Рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй способ соответсвует нумерации элементов треугольника числом отрезков каждого типа на путях, ведущих в соответствующую точку (рис.&amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;C_{n,m} = c_{n+m, n} = \begin{pmatrix} n + m \\ m \end{pmatrix}&amp;lt;/tex&amp;gt;. Тогда производящая функция будет иметь вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n,m = 0}^{\infty} C_{n, m} x^n y^m = \sum\limits_{n,m = 0}^{\infty}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{k = 0}^{\infty} \sum\limits_{n + m = k}  \begin{pmatrix} n + m \\ n \end{pmatrix}&lt;br /&gt;
x^n y^m = \sum\limits_{k = 0}^{\infty} (x + y)^k = \dfrac{1}{1 -x - y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует еще один способ: сопоставить треугольнику Паскаля ''экспоненциальную производящую функцию''. Экспоненциальная производящая функция отличается от обычной тем, что в качестве коэффициентов степенного ряда берутся не элементы последовательности &amp;lt;tex&amp;gt;a_n&amp;lt;/tex&amp;gt;, а числа &amp;lt;tex&amp;gt;\dfrac{a_n}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Экспоненциальные производящие функции==&lt;br /&gt;
&lt;br /&gt;
Зафиксируем произвольную последовательность &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Каждой последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; мы можем сопоставить производящую функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\{ \alpha_n \} \mapsto \sum\limits_{n = 0}^{\infty} a_n \alpha_n s^n&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
определяемую последовательностью &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt;. Если в последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \}&amp;lt;/tex&amp;gt; отсутствуют нулевые элементы, то такое сопоставление взаимно однозначно. До сих пор мы пользовались обычными производящими функциями - отвечающими последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} \equiv 1&amp;lt;/tex&amp;gt;. В зависимости от преследуемых целей целей могут принести и другие последовательности . &lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящие экспоненциальные функции''' (англ. ''exponential generating function'') {{---}} функции, соответсвующие последовательности &amp;lt;tex&amp;gt;\{ \alpha_n \} = \dfrac{1}{n!}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
Экспоненциальные производящие функции для целочисленных последовательностей называют '''функциями Гурвица''' (англ. ''Hurwitz function'').&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чем отличаются экспоненциальные производящие функции от обычных? Посмотрим на поведение экспоненциальных производящих функций при выполнении операции над ними. Сумма ведет себя обычным образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n = 0}^{\infty} \dfrac{a_n}{n!}s^n + \sum\limits_{n = 0}^{\infty} \dfrac{b+n}{n!}s^n = \sum\limits_{n = 0}^{\infty} \dfrac{(a_n + b_n)}{n!} s^n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а с произведением по-другому :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots\bigg)\bigg(\dfrac{b_0}{0!} + \dfrac{b_1}{1!}s + \dfrac{b_2}{2!}s^2 + \ldots\bigg) = \dfrac{a_0}{0!} \dfrac{b_0}{0!} + \bigg(\dfrac{a_0}{0!} \dfrac{b_1}{1!} + \dfrac{a_1}{1!} \dfrac{b_0}{0!}\bigg)s + \bigg(\dfrac{a_0}{0!} \dfrac{b_2}{2!} + \dfrac{a_1}{1!} \dfrac{b_1}{1!} + \dfrac{a_2}{2!} \dfrac{b_0}{0!}\bigg)s^2 + \ldots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициенты &amp;lt;tex&amp;gt;\dfrac{c_n}{n!}&amp;lt;/tex&amp;gt; произведения вычисляются по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;c_n = \begin{pmatrix} n \\ 0 \end{pmatrix} a_0 b_n + \begin{pmatrix} n \\ 1 \end{pmatrix} a_1 b_{n - 1} + \ldots + \begin{pmatrix} n \\ n \end{pmatrix} a_0 b_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Еще одно существенное отличие экспоненциальных производящих функций от обычных наблюдается при взятии производных (и интегрировании). Дифференцирование или интегрирование экспоненциальной производящей функции приводит к сдвигу последовательности ее коэффициентов без изменения их велечины: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\bigg( \dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg)^{'} = \dfrac{a_1}{0!} + \dfrac{a_2}{1!}s + \dfrac{a_3}{2!}s^2 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\int \bigg(\dfrac{a_0}{0!} + \dfrac{a_1}{1!}s + \dfrac{a_2}{2!}s^2 + \ldots \bigg) = \dfrac{a_0}{1!}s + \dfrac{a_1}{2!}s^2 + \dfrac{a_2}{3!}s^3 + \dfrac{a_3}{4!}s^4 + \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обычная производящая функция &amp;lt;tex&amp;gt;A(s) = a_0 + a_1s + a_2s^2 + \ldots&amp;lt;/tex&amp;gt; выражается через экспоненциальную &amp;lt;tex&amp;gt;B(t) = \dfrac{a_0}{0!} + \dfrac{a_1}{1!}t + \dfrac{a_2}{2!}t^2 + \ldots &amp;lt;/tex&amp;gt; по формуле &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s) = \int_{0}^{\infty} e^{-t} B(st) dt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Действительно, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k! = \int_{0}^{\infty} e^{-t}t^kdt&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно выписать экспоненциальную производящую функцию для треугольника Паскаля:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n, m = 0}^{\infty} \dfrac{1}{(n + m)!}  \begin{pmatrix} n + m \\ m \end{pmatrix} x^n y^m = \sum\limits_{n = 0}^{\infty} \dfrac{(x + y)^n}{n!} = e^{x + y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Многочлены Бернулли==&lt;br /&gt;
Для начала введен операцию ''усреднения'', положив&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(f(x)) = \int_{x}^{x+1}f(t)dt&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что эта операция переводит многочлены в многочлены: она линейна, т.е. &amp;lt;tex&amp;gt;A(a_1f_1 + a_2f_2) = a_1A(f_1) + a_2A(f_2)&amp;lt;/tex&amp;gt; для любых постоянных &amp;lt;tex&amp;gt;a_1, a_2&amp;lt;/tex&amp;gt; и любых многочленов &amp;lt;tex&amp;gt;f_1,&lt;br /&gt;
 f_2&amp;lt;/tex&amp;gt;, а ее значение на мономе&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%87%D0%BB%D0%B5%D0%BD Моном]&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt; равно&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(x^n) = ((x + 1)^{n+1} - x^{n+1}) / (n+1) = x^n + \ldots&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где многоточие обозначает слагаемые, степени которых меньше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Последняя формула показывает также, что преобразование &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; переводит пространство многочленов степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; в себя, а значит, является линейным оператором в этом пространстве. Этот оператор обратим. Действительно, любой многочлен степени не выше &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; может быть получен в результате усреднения многочлена такой же степени, и, используя последнюю формулу, мы заключаем, что и любой многочлен степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; является результатом усреднения некоторого многочлена степени не выше &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Отметим, что при усреднении степень многочлена сохраняется.&lt;br /&gt;
&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Многочленом Бернулли''' (англ. ''Bernoulli polynomial'') степени &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; называется многочлен &amp;lt;tex&amp;gt;B_n(x)&amp;lt;/tex&amp;gt;, результатом усреднения которого служит моном &amp;lt;tex&amp;gt;x^n&amp;lt;/tex&amp;gt;, т.е. &amp;lt;tex&amp;gt;B_n(x) = A^{-1}(x^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Первые многочлены Бернулли нетрудно сосчитать:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_0(x) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_1(x) = x - \dfrac{1}{2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_2(x) = x^2 -x + \dfrac{1}{6}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_3(x) = x^3 - \dfrac{3}{2}x^2 + \dfrac{1}{2}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_4(x) = x^4 - 2x^3 + x^2 - \dfrac{1}{30}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_5(x) = x^5 - \dfrac{5}{2}x^4 + \dfrac{5}{3}x^3 - \dfrac{1}{6}x&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;B_6(x) = x^6 - 3x^5 + \dfrac{5}{2}x^4 - \dfrac{1}{2}x^2 + \dfrac{1}{42}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
| about = Экспоненциальная производящая функция для многочленов Бернулли&lt;br /&gt;
| statement = &lt;br /&gt;
Экспоненциальная производящая функция для многочленов Бернулли имеет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathcal{B}(x, s) = \sum\limits_{n=0}^{\infty}B_n(x)\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}e^{sx}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
| proof = &lt;br /&gt;
Для доказательства теоремы достаточно применить операцию усреднения к левой и правой частям равенства. С одной стороны, мы имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(B(x, s)) = \sum\limits_{n=0}^{\infty}A(B_n(x))\dfrac{s^n}{n!} = \sum\limits_{n=0}^{\infty}x^n\dfrac{s^n}{n!} = e^{xs}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С другой стороны, имеем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(\dfrac{s}{e^s - 1}e^{sx}) = \dfrac{s}{e^s-1}A(e^{sx}) = \dfrac{s}{e^s-1}\dfrac{1}{s}(e^{s(x+1)} - e^{sx}) = e^{sx}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
и теорема доказана.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Определим теперь ''числа Бернулли''&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%91%D0%B5%D1%80%D0%BD%D1%83%D0%BB%D0%BB%D0%B8 числа Бернулли]&amp;lt;/ref&amp;gt; как значения многочленов Бернулли в нуле. Вот начало последовательности чисел Бернулли:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;1, -\dfrac{1}{2}, 0, \dfrac{1}{6}, -\dfrac{1}{30}, \dfrac{1}{42}, 0, -\dfrac{1}{30}, \dfrac{5}{66}, 0, -\dfrac{691}{2730}, 0, \ldots &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Доказанная теорема позволяет нам легко выписать экспоненциальную производящую функцию для чисел Бернулли. Для этого достаточно подставить в экспоненциальную производящую функцию для многочленов Бернулли значение &amp;lt;tex&amp;gt;x = 0&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{n=0} B_n\dfrac{s^n}{n!} = \dfrac{s}{e^s - 1}&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;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 57с. ISBN 978-5-94057-042-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Производящая функция]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F_%D1%81_%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC%D0%B8_%D1%81%D1%82%D0%B5%D0%BF%D0%B5%D0%BD%D0%BD%D1%8B%D0%BC%D0%B8_%D1%80%D1%8F%D0%B4%D0%B0%D0%BC%D0%B8&amp;diff=63852</id>
		<title>Арифметические действия с формальными степенными рядами</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F_%D1%81_%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC%D0%B8_%D1%81%D1%82%D0%B5%D0%BF%D0%B5%D0%BD%D0%BD%D1%8B%D0%BC%D0%B8_%D1%80%D1%8F%D0%B4%D0%B0%D0%BC%D0%B8&amp;diff=63852"/>
				<updated>2018-03-01T14:29:32Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Сдвиг влево */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Простейшие операции==&lt;br /&gt;
Рассмотрим два [[Производящая функция|формальных степенных ряда]] &amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + \dots&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B(s) = b_0 + b_1 s + b_2 s^2 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition = '''Суммой''' (англ. ''addition'') формальных степенных рядов &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; называется ряд &amp;lt;tex&amp;gt;A(s) + B(s) = (a_0 + b_0) + (a_1 + b_1) s + (a_2 + b_2) s^2 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition = '''Произведением''' (англ. ''multiplication'') формальных степенных рядов &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; называется ряд &amp;lt;tex&amp;gt;A(s)B(s) = a_0 b_0 + (a_0 b_1 + a_1 b_0) s + (a_0 b_2 + a_1 b_1 + a_2 b_0) s^2 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Операции сложения и умножения формальных степенных рядов коммутативны и ассоциативны.&lt;br /&gt;
&lt;br /&gt;
==Деление==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Обратным по умножению''' (англ. ''multiplicative inverse'') к формальному степенному ряду &amp;lt;tex&amp;gt;A(s)&amp;lt;/tex&amp;gt; называется такой ряд &amp;lt;tex&amp;gt;B(s)&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;A(s)B(s) = 1&amp;lt;/tex&amp;gt;. Обозначение: &amp;lt;tex&amp;gt;B(s) = A^{-1}(s)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement = Пусть &amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + a_3 s^3 + \dots &amp;lt;/tex&amp;gt; {{---}} формальный степенной ряд, причем &amp;lt;tex&amp;gt;A(0) \ne 0&amp;lt;/tex&amp;gt;. Тогда существует единственный обратный по умножению к &amp;lt;tex&amp;gt;A(s)&amp;lt;/tex&amp;gt; ряд &amp;lt;tex&amp;gt;B(s) = b_0 + b_1 s + b_2 s^2 + b_3 s^3 + \dots &amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof = &lt;br /&gt;
:Распишем &amp;lt;tex&amp;gt;A(s)B(s)&amp;lt;/tex&amp;gt; по формуле произведения рядов: &amp;lt;tex&amp;gt;A(s)B(s) = a_0 b_0 + (a_0 b_1 + a_1 b_0)s + (a_0 b_2 + a_1 b_1 + a_2 b_0) s^2 + \dots&amp;lt;/tex&amp;gt;. Заметим, что условие &amp;lt;tex&amp;gt;A(s)B(s) = 1&amp;lt;/tex&amp;gt; выполнено только в том случае, если &amp;lt;tex&amp;gt;a_0 b_0 = 1&amp;lt;/tex&amp;gt;, а все остальные слагаемые полученного ряда равны нулю. &lt;br /&gt;
:Докажем по индукции, что такой ряд &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; единственен. Нам известно, что &amp;lt;tex&amp;gt;b_0 = \dfrac{1}{a_0}&amp;lt;/tex&amp;gt;. Пусть теперь все коэффициенты ряда &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; вплоть до степени &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; однозначно определены. Коэффициент при &amp;lt;tex&amp;gt;s^n&amp;lt;/tex&amp;gt; определяется из условия &amp;lt;tex&amp;gt;a_0 b_n + a_1 b_{n - 1} + \dots + a_n b_0 = 0&amp;lt;/tex&amp;gt;. Это линейное уравнение на &amp;lt;tex&amp;gt;b_n&amp;lt;/tex&amp;gt;, причем коэффициент &amp;lt;tex&amp;gt;a_0&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;b_n&amp;lt;/tex&amp;gt; отличен от нуля. Такое уравнение имеет единственное решение.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Делением''' (англ. ''division'') формальных степенных рядов &amp;lt;tex&amp;gt;A(s)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B(s)&amp;lt;/tex&amp;gt; называется операция &amp;lt;tex&amp;gt;\dfrac{A(s)}{B(s)} = A(s) B(s)^{-1}&amp;lt;/tex&amp;gt; (при условии существования у &amp;lt;tex&amp;gt;B(s)&amp;lt;/tex&amp;gt; обратного).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
#Допустим, надо построить обратный ряд для &amp;lt;tex&amp;gt;A(s) = 1 + s&amp;lt;/tex&amp;gt;. Воспользуемся леммой:&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_0 = \dfrac{1}{a_0} = \dfrac{1}{1} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;a_0 b_1 + a_1 b_0 = 0 \Rightarrow b_1 = - \dfrac{a_1 b_0}{a_0} = - \dfrac{1 \cdot 1}{1} = -1&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;a_0 b_2 + a_1 b_1 + a_2 b_0 = 0 \Rightarrow b_2 = - \dfrac{a_1 b_1 + a_2 b_0}{a_0} = - \dfrac{1 \cdot (-1) + 0}{1} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;\dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_n = - \dfrac{a_1 b_{n - 1}}{a_0} = -b_{n - 1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;B(s) = 1 - s + s^2 - s^3 + \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
#Пусть теперь надо построить обратный ряд для &amp;lt;tex&amp;gt;A(s) = 1 - s - s^2&amp;lt;/tex&amp;gt;:&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_0 = \dfrac{1}{a_0} = \dfrac{1}{1} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_1 = - \dfrac{a_1 b_0}{a_0} = - \dfrac{(-1) \cdot 1}{1} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_2 = - \dfrac{a_1 b_1 + a_2 b_0}{a_0} = - \dfrac{(-1) \cdot 1 + (-1) \cdot 1}{1} = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_3 = - \dfrac{a_1 b_2 + a_2 b_1}{a_0} = - \dfrac{(-1) \cdot 2 + (-1) \cdot 1}{1} = 3&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;\dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;b_n = - \dfrac{a_1 b_{n - 1} + a_2 b_{n - 2}}{a_0} = b_{n - 1} + b_{n - 2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
#:&amp;lt;tex&amp;gt;B(s) = 1 + s + 2 s^2 + 3 s^3 + \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Композиция==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + \dots&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B(s) = b_0 + b_1 s + b_2 s^2 + \dots&amp;lt;/tex&amp;gt; {{---}} два формальных степенных ряда, причем &amp;lt;tex&amp;gt;B(0) = b_0 = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition = &lt;br /&gt;
'''Композицией (подстановкой)''' (англ. ''composition'') формальных степенных рядов &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; называется ряд &amp;lt;tex&amp;gt;A(B(t)) = a_0 + a_1 b_1 t + (a_1 b_2 + a_2 b_1^2) t^2 + (a_1 b_3 + 2 a_2 b_1 b_2 + a_3 b_1^3) t^3 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Если, например, &amp;lt;tex&amp;gt;B(t) = -t&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A(B(t)) = A(-t) = a_0 -a_1 t + a_2 t^2 - a_3 t^3 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Операция подстановки в случае, когда &amp;lt;tex&amp;gt;B(0) \ne 0&amp;lt;/tex&amp;gt;, не определена. (При попытке подставить такой ряд для вычисления коэффициентов результата возникает необходимость суммирования бесконечных числовых рядов).&lt;br /&gt;
&lt;br /&gt;
==Обратный ряд==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Левым обратным''' (англ. ''left inverse'') по операции подстановки формальным степенным рядом для ряда &amp;lt;tex&amp;gt;B(t)&amp;lt;/tex&amp;gt; называется такой ряд &amp;lt;tex&amp;gt;A(s)&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;A(B(t)) = t&amp;lt;/tex&amp;gt;. Аналогично, '''правым обратным''' (англ. ''right inverse'') формальным степенным рядом для &amp;lt;tex&amp;gt;B(t)&amp;lt;/tex&amp;gt; называется такой &amp;lt;tex&amp;gt;C(u)&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;B(C(u)) = u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема &lt;br /&gt;
|about = об обратном формальном степенном ряде&lt;br /&gt;
|statement = Пусть ряд &amp;lt;tex&amp;gt;B(t) = b_0 + b_1 t + b_2 t^2 + b_3 t^3 + \dots&amp;lt;/tex&amp;gt; таков, что &amp;lt;tex&amp;gt;B(0) = b_0 = 0&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;b_1 \ne 0&amp;lt;/tex&amp;gt;. Тогда существуют такие ряды &amp;lt;tex&amp;gt; A(s) = a_1 s + a_2 s^2 + a_3 s^3 + \dots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;A(0) = 0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C(u) = c_1 u + c_2 u^2 + c_3 u^3 + \dots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;C(0) = 0&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;A(t)&amp;lt;/tex&amp;gt; является левым обратным, а &amp;lt;tex&amp;gt;C(u)&amp;lt;/tex&amp;gt; {{---}} правым обратным для &amp;lt;tex&amp;gt;B(s)&amp;lt;/tex&amp;gt;. При этом, ряды &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; единственны. &lt;br /&gt;
|proof =&lt;br /&gt;
:Докажем по индукции существование и единственность левого обратного ряда. Доказательство для правого аналогично. &lt;br /&gt;
:Будем определять коэффициенты ряда &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; последовательно. Поскольку &amp;lt;tex&amp;gt;A(B(t)) = t&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_1 b_1 = 1&amp;lt;/tex&amp;gt;, откуда &amp;lt;tex&amp;gt;a_1 = \dfrac{1}{b_1}&amp;lt;/tex&amp;gt;. Все остальные коэффициенты результирующего ряда при этом равны нулю.&lt;br /&gt;
:Предположим теперь, что коэффициенты &amp;lt;tex&amp;gt;a_1, a_2, \dots, a_n&amp;lt;/tex&amp;gt; уже определены. Коэффициент &amp;lt;tex&amp;gt;a_{n+1}&amp;lt;/tex&amp;gt; определяется из условия &amp;lt;tex&amp;gt;a_{n+1} b_1^{n+1} + \dots = 0&amp;lt;/tex&amp;gt;, где точками обозначен некоторый многочлен от &amp;lt;tex&amp;gt;a_1, \dots, a_n&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_1, \dots, b_n&amp;lt;/tex&amp;gt;. Тем самым, условие представляет собой линейное уравнение на &amp;lt;tex&amp;gt;a_{n+1}&amp;lt;/tex&amp;gt;, причем коэффициент &amp;lt;tex&amp;gt;b_1^{n+1}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;a_{n+1}&amp;lt;/tex&amp;gt; отличен от нуля. Такое уравнение имеет единственное решение, и теорема доказана.&lt;br /&gt;
}}&lt;br /&gt;
===Пример===&lt;br /&gt;
Найдем левый обратный ряд для &amp;lt;tex&amp;gt;B(t) = t + t^2&amp;lt;/tex&amp;gt;:&lt;br /&gt;
:&amp;lt;tex&amp;gt;a_0 = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;a_1 = \dfrac{1}{b_1} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;a_1 b_2 + a_2 b_1^2 = 0 \Rightarrow a_2 = - \dfrac{a_1 b_2}{b_1^2} = - \dfrac{1 \cdot 1}{1^2} = -1&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;a_1 b_3 + 2 a_2 b_1 b_2 + a_3 b_1^3 = 0 \Rightarrow a_3 = - \dfrac{a_1 b_3 + 2 a_2 b_1 b_2}{b_1^3} = - \dfrac{1 \cdot 0 + 2 \cdot (-1) \cdot 1}{1^3} = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;\dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;A(s) = s - s^2 + 2 s^3 + \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Сдвиги==&lt;br /&gt;
===Сдвиг вправо===&lt;br /&gt;
Сдвиг ряда вправо на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; получается домножением его на &amp;lt;tex&amp;gt;s^k&amp;lt;/tex&amp;gt;. Например, пусть исходный ряд &amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + \dots&amp;lt;/tex&amp;gt;. Сдвинем его на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; вправо: &amp;lt;tex&amp;gt;B(s) = s^k \cdot A(s) = a_0 s^k + a_1 s^{k + 1} + a_2 s^{k + 2} + \dots = 0 + 0 s + 0 s^2 + \dots + a_0 s^k + a_1 s^{k + 1} + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Сдвиг влево===&lt;br /&gt;
Сдвинуть ряд влево на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; можно, вычтя из него первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; слагаемых и затем разделив его на &amp;lt;tex&amp;gt;s^k&amp;lt;/tex&amp;gt;. Например, сдвинем ряд &amp;lt;tex&amp;gt;A(s) = a_0 + a_1 s + a_2 s^2 + \dots&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; влево: &amp;lt;tex&amp;gt;B(s) = \dfrac{A(s) - (a_0 + a_1 s + a_2 s^2 + \dots + a_{k - 1} s^{k - 1})}{s^k} = a_k + a_{k + 1} s + a_{k + 2} s^2 + \dots&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Сдвиги могут быть полезны для упрощения вычисления производящих функций.&lt;br /&gt;
Например, попробуем получить функцию для чисел Фибоначчи, используя сдвиги. Пусть формальный степенной ряд для нее равен &amp;lt;tex&amp;gt;F(s) = f_0 + f_1 s + f_2 s^2 + \dots&amp;lt;/tex&amp;gt;, при этом &amp;lt;tex&amp;gt;f_0 = f_1 = 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;f_n = f_{n - 2} + f_{n - 1}, n &amp;gt; 1&amp;lt;/tex&amp;gt;. Рассмотрим сумму этого ряда и ряда, полученного из него сдвигом на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; вправо: &amp;lt;tex&amp;gt;F(s) + s \cdot F(s) = (f_0 + f_1 s + f_2 s^2 + f_3 s^3 + \dots) + (0 + f_0 s + f_1 s^2 + f_2 s^3 + \dots) = (f_0 + 0) + (f_1 + f_0) s + (f_2 + f_1) s^2 + (f_3 + f_2) s^3 + \dots = f_1 + f_2 s + f_3 s^2 + f_4 s^3 + \dots&amp;lt;/tex&amp;gt;. Заметим, что результат равен сдвигу &amp;lt;tex&amp;gt;F(s)&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Составим и решим уравнение: &amp;lt;tex&amp;gt;F(s) + s \cdot F(s) = \dfrac{F(s) - 1}{s}&amp;lt;/tex&amp;gt;; &amp;lt;tex&amp;gt;F(s)(s^2 + s - 1) = -1&amp;lt;/tex&amp;gt;; &amp;lt;tex&amp;gt;F(s) = \dfrac{1}{1 - s - s^2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Производящая функция]]&lt;br /&gt;
* [[Производящие функции нескольких переменных]]&lt;br /&gt;
* [[Разложение рациональной функции в ряд]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* ''Ландо С. К.'', Лекции о производящих функциях. {{---}} 3-е изд., испр. {{---}} М.: МЦНМО, 2007. {{---}} 144с. ISBN 978-5-94057-042-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Комбинаторика]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B0%D1%8F_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F_%D0%94%D0%B8%D1%80%D0%B8%D1%85%D0%BB%D0%B5&amp;diff=63822</id>
		<title>Производящая функция Дирихле</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B0%D1%8F_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F_%D0%94%D0%B8%D1%80%D0%B8%D1%85%D0%BB%D0%B5&amp;diff=63822"/>
				<updated>2018-02-24T19:38:31Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Обратимость */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Производящая функция Дирихле''' (англ. ''Dirichlet generating functions'') последовательности &amp;lt;tex&amp;gt;\{a_n\}_{n=1}^{\infty}&amp;lt;/tex&amp;gt; — это формальный ряд вида: &lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;A(s)= \frac{a_1}{1^s} + \frac{a_2}{2^s} + \frac{a_3}{3^s} + \dots = \sum\limits_{n=1}^\infty \frac{a_n}{n^s}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Примечание ==&lt;br /&gt;
* Нумерация коэффициентов производящих функций Дирихле начинается с единицы, а не с нуля, как это было в случае обыкновенных производящих функций. &lt;br /&gt;
* Вместо переменной &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; используется &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Это изменение связано больше с традициями, чем с математикой. &lt;br /&gt;
* Принято писать &amp;lt;tex&amp;gt; \frac{a_n}{n^s} &amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt; {a_n}{n^{-s}} &amp;lt;/tex&amp;gt;. Это считается более удобной формой. &lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
&lt;br /&gt;
Самой известной среди производящих функций Дирихле является дзета-функция Римана &lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Дзета-функция Римана ''' (англ. ''The Riemann zeta function'') — производящая функция Дирихле, отвечающая последовательности &amp;lt;tex&amp;gt; \{a_n\}_{n=1}^{\infty} &amp;lt;/tex&amp;gt;, состоящей из единиц:&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\zeta (s)={\frac {1}{1^{s}}}+{\frac {1}{2^{s}}}+{\frac {1}{3^{s}}}+\ldots ,&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таблица содержит известные производящие функции. Первая из них — это дзета-функция Римана, состоящая из единиц. &amp;lt;tex&amp;gt;[\zeta(s)]^2&amp;lt;/tex&amp;gt; является последовательностью количества делителей числа. &amp;lt;tex&amp;gt;\mu(n)&amp;lt;/tex&amp;gt; — последовательность Мҷбиуса (англ. Möbius). &amp;lt;tex&amp;gt;H(n)&amp;lt;/tex&amp;gt; — последоватльность факторизаций числа. &amp;lt;tex&amp;gt;\phi(n)&amp;lt;/tex&amp;gt; — функция Эйлера. &amp;lt;tex&amp;gt;\lambda(s)&amp;lt;/tex&amp;gt; — лямбда функция Дирихле.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:20cm&amp;quot; border=1&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;center&amp;quot; bgcolor=#EEEEFF&lt;br /&gt;
| '''&amp;lt;tex&amp;gt;f(s)&amp;lt;/tex&amp;gt;''' || '''Последоватльность''' || '''&amp;lt;tex&amp;gt;{a_n}&amp;lt;/tex&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;\zeta(s)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, 1, 1, 1, 1, 1, 1, 1, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;1/\zeta(s)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\mu(n)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, -1, -1, 0, -1, 1, -1, 0, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;[\zeta(s)]^2&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;d(n)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, 2, 2, 3, 2, 4, 2, 4, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;\zeta(s)\zeta(s-k)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\sigma_k(n)&amp;lt;/tex&amp;gt; || &lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;\zeta(s-1)/\zeta(s)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\phi(n)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, 1, 2, 2, 4, 2, 6, 4, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;1/[2-\zeta(s)]&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;H(n)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, 1, 1, 2, 1, 3, 1, 4, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;\lambda(s)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1/2[1-(-1)^n]&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, 0, 1, 0, 1, 0, 1, 0, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; bgcolor=#FFFFFF&lt;br /&gt;
| &amp;lt;tex&amp;gt;(\zeta(s)\zeta(s-1))/(\zeta(2s))&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\psi(n)&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1, 3, 4, 6, 6, 12, 8, 12, \dots&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
== Операции ==&lt;br /&gt;
&lt;br /&gt;
Производящие функции Дирихле чаще используются в мультипликативной теории чисел, ввиду особого поведения относительно умножения. &lt;br /&gt;
&lt;br /&gt;
=== Умножение ===&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;A(s)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B(s)&amp;lt;/tex&amp;gt; — произодящие функции Дирихле двух последовательностей &amp;lt;tex&amp;gt;\{a_n\}_{n=1}^\infty&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\{b_n\}_{n=1}^\infty&amp;lt;/tex&amp;gt; соответсвенно, то &amp;lt;tex&amp;gt;A(s)B(s) = \frac{a_1b_1}{1^s} + \frac{a_1b_2 + a_2b_1}{2^s} + \frac{a_1b_3 + a_3b_1}{3^s} + \frac{a_1b_4 + a_2b_2 + a_4b_1}{4^s} + \dots = \sum\limits_{n} \frac{\sum\limits_{kl=n} {a_kb_l}}{n^s}&amp;lt;/tex&amp;gt;, где внутренние суммирование ведется по всем разложением числа &amp;lt;tex&amp;gt;n&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;
Роль единицы при умножении производящих функций Дирихле играет функция &amp;lt;tex&amp;gt;1 = 1 ^ {-s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Обратимость ===&lt;br /&gt;
&lt;br /&gt;
Любая производящая функция Дирихле &amp;lt;tex&amp;gt;A(s)&amp;lt;/tex&amp;gt; с ненулевым свободным членом, &amp;lt;tex&amp;gt;a_1 \neq 0&amp;lt;/tex&amp;gt;, обратима: для нее существует функция &amp;lt;tex&amp;gt;B(s)&amp;lt;/tex&amp;gt;, такая что &amp;lt;tex&amp;gt;A(s)B(s) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attention!&lt;br /&gt;
Можно привести доказательство теоремы об обратной функции для дзета-функции Римана &amp;lt;!---лол, это была не я. (МК)---&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации == &lt;br /&gt;
* [http://files.school-collection.edu.ru/dlrstore/d62ef84c-a780-11dc-945c-d34917fee0be/47_lando_lekcii_o_proizvodyashih_foo.pdf С.К.Ландо, Леции о производящих функциях, 2007 год]&lt;br /&gt;
* [http://mathworld.wolfram.com/DirichletGeneratingFunction.html Dirichlet Generating Function]&lt;br /&gt;
* [https://mathlesstraveled.com/2017/01/30/dirichlet-generating-functions/ Dirichlet generating functions]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Комбинаторика]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%AD%D0%B4%D0%BC%D0%BE%D0%BD%D0%B4%D1%81%D0%B0-%D0%9A%D0%B0%D1%80%D0%BF%D0%B0&amp;diff=63774</id>
		<title>Алгоритм Эдмондса-Карпа</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D0%B4%D0%BC%D0%BE%D0%BD%D0%B4%D1%81%D0%B0-%D0%9A%D0%B0%D1%80%D0%BF%D0%B0&amp;diff=63774"/>
				<updated>2018-02-17T18:02:24Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Алгоритм ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Эдмондса-Карпа является реализацией метода [[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания|Форда-Фалкерсона]], в которой в качестве дополняющего пути выбирается [[Обход в ширину |кратчайший по рёбрам путь]] в остаточной сети (длины всех рёбер равны &amp;lt;tex&amp;gt;1&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;
## На найденном пути в остаточной сети ищем ребро с минимальной пропускной способностью &amp;lt;tex&amp;gt;\mathrm{c_{min}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Для каждого ребра на найденном пути увеличиваем поток на &amp;lt;tex&amp;gt;\mathrm{c_{min}}&amp;lt;/tex&amp;gt;, а в противоположном ему — уменьшаем на &amp;lt;tex&amp;gt;\mathrm{c_{min}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Модифицируем остаточную сеть. Для всех рёбер на найденном пути, а также для противоположных им рёбер, вычисляем новую пропускную способность. Если она стала ненулевой, добавляем ребро к остаточной сети, а если обнулилась, стираем его.&lt;br /&gt;
# Возвращаемся на шаг 2.&lt;br /&gt;
&lt;br /&gt;
===Сложность===&lt;br /&gt;
Сложность алгоритма Эдмондса-Карпа равна &amp;lt;tex&amp;gt;O(VE^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''function''' EdmondsKarp(G, s, t):&lt;br /&gt;
     '''for''' (для) каждого ребра &amp;lt;tex&amp;gt;(u,v) \in E[G]&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;f[u,v] \leftarrow 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;f[v,u] \leftarrow 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' существует ''кратчайший'' путь &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; в остаточной сети &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;c_f(p) \leftarrow min\{c_f(u,v) : (u,v) \in p\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''for''' &amp;lt;tex&amp;gt;(u,v) \in p&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;f[u,v] \leftarrow f[u,v] + c_f(p)&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;f[v,u] \leftarrow -f[u,v]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Корректность алгоритма Эдмондса-Карпа ==&lt;br /&gt;
&lt;br /&gt;
На каждой итерации цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; поток в графе &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; увеличивается вдоль одного из кратчайших путей в &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt; из истока &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в сток &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. Этот процесс повторяется до тех пор пока существует кратчайший &amp;lt;tex&amp;gt;s \leadsto t&amp;lt;/tex&amp;gt; путь в &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt;. Если в &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt; не существует кратчайшего пути из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, значит, не существует вообще никакого &amp;lt;tex&amp;gt;s \leadsto t&amp;lt;/tex&amp;gt; пути в &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt; следовательно по [[Теорема Форда-Фалкерсона|теореме Форда-Фалкерсона]] найденный поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; максимальный.&lt;br /&gt;
&lt;br /&gt;
== Оценка быстродействия ==&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|statement=&lt;br /&gt;
Если в сети &amp;lt;tex&amp;gt;G(V,E)&amp;lt;/tex&amp;gt; с истоком &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; увеличение потока производится вдоль кратчайших &amp;lt;tex&amp;gt;s \leadsto t&amp;lt;/tex&amp;gt; путей в &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt;, то для всех вершин &amp;lt;tex&amp;gt;v \in V\backslash\{s,t\}&amp;lt;/tex&amp;gt; длина кратчайшего пути &amp;lt;tex&amp;gt;\delta_f(s, v)&amp;lt;/tex&amp;gt; в остаточной сети &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt; не убывает после каждого увеличения потока.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим противное, пусть существует вершина &amp;lt;tex&amp;gt;v \in V \backslash\{s,t\}&amp;lt;/tex&amp;gt;, что после какого-то увеличения потока длина кратчайшего пути из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; уменьшилась. Обозначим потоки до и после увеличения соответственно за &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; {{---}} вершина, расстояние &amp;lt;tex&amp;gt;\delta'_f(s,v)&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до которой минимально и уменьшилось с увеличением потока. Имеем &amp;lt;tex&amp;gt;\delta'_f(s,v) &amp;lt; \delta_f(s,v)&amp;lt;/tex&amp;gt;. Рассмотрим путь &amp;lt;tex&amp;gt;p = s \leadsto u \rightarrow v&amp;lt;/tex&amp;gt;, являющийся кратчайшим от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; к &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;G'_f&amp;lt;/tex&amp;gt;. Тогда верно, что &amp;lt;tex&amp;gt;\delta'_f(s, u) = \delta'_f(s,v) - 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
По выбору &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и из предыдущего утверждения получаем, что &amp;lt;tex&amp;gt;\delta'_f (s, u) \geqslant\delta_f(s,u)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;(u, v) \in E_f&amp;lt;/tex&amp;gt;, тогда &amp;lt;tex&amp;gt;\delta_f(s,v) \leqslant \delta_f(s, u) + 1 \leqslant \delta'_f(s,u) + 1 = \delta'_f(s, v)&amp;lt;/tex&amp;gt;. Это противоречит &amp;lt;tex&amp;gt;\delta'_f(s,v) &amp;lt; \delta_f(s,v)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;(u,v) \notin E_f&amp;lt;/tex&amp;gt;, но известно, что &amp;lt;tex&amp;gt;(u,v) \in E_f'&amp;lt;/tex&amp;gt;. Появление ребра &amp;lt;tex&amp;gt;(u,v)&amp;lt;/tex&amp;gt; после увеличения потока означает увеличение потока по обратному ребру &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt;. Увеличение потока производится вдоль кратчайшего пути, поэтому кратчайший путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; вдоль которого происходило увеличения выглядит как &amp;lt;tex&amp;gt;s \leadsto v \rightarrow u&amp;lt;/tex&amp;gt;, из чего получаем &amp;lt;tex&amp;gt;\delta_f(s, v) = \delta_f(s, u) - 1 \leqslant \delta'_f(s, u) - 1 = \delta'(s, v) - 2&amp;lt;/tex&amp;gt;. Данное утверждение противоречит &amp;lt;tex&amp;gt;\delta'_f(s,v) &amp;lt; \delta_f(s,v)&amp;lt;/tex&amp;gt;. Итак мы пришли к противоречию с существованием вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, кратчайшее расстояние до которой уменьшилось с увеличением потока.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Опираясь на предшествующую лемму, докажем следующую теорему, которая ограничивает сверху число итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt;  в алгоритме Эдмондса-Карпа.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Пусть для некоторой сети &amp;lt;tex&amp;gt;G(V,E)&amp;lt;/tex&amp;gt; с источником &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; выполняется алгоритм Эдмондса-Карпа, тогда общее число итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt;  составляет &amp;lt;tex&amp;gt;O(V E)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим множество рёбер &amp;lt;tex&amp;gt;(u,v)&amp;lt;/tex&amp;gt; остаточной сети &amp;lt;tex&amp;gt;G_f&amp;lt;/tex&amp;gt;, принадлежащих увеличивающему пути &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;c_f(p) = c_f(u,v)&amp;lt;/tex&amp;gt;. Назовем данные рёбра критическими. Покажем, что каждое из &amp;lt;tex&amp;gt;|E|&amp;lt;/tex&amp;gt; рёбер может становиться критическим не более, чем &amp;lt;tex&amp;gt;|V| - 1&amp;lt;/tex&amp;gt; раз. Заметим, что после увеличения потока вдоль пути &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; все критические рёбра исчезают из остаточной сети, кроме того по определению остаточной пропускной способности пути хотя бы одно ребро увеличивающего пути {{---}} критическое.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим две вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; принадлежащие &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;, соединенные некоторым ребром из &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;. Увеличение производится вдоль кратчайших путей, поэтому если ребро &amp;lt;tex&amp;gt;(u,v)&amp;lt;/tex&amp;gt; становиться критическим в первый раз, верно, что &amp;lt;tex&amp;gt;\delta_f(s,v) = \delta_f(s,u) + 1&amp;lt;/tex&amp;gt;. После увеличения потока ребро &amp;lt;tex&amp;gt;(u, v)&amp;lt;/tex&amp;gt; исчезает из сети. Оно не появится в другом увеличивающем пути до тех, пор пока не будет уменьшено по обратному ребру &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt;. Это может произойти только в том случае, если ребро &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt; встретится на некотором увеличивающем пути. Пусть в момент перед увеличением поток в сети &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; составлял &amp;lt;tex&amp;gt;f'&amp;lt;/tex&amp;gt;, то поскольку увеличение производиться вдоль кратчайших путей, верно: &amp;lt;tex&amp;gt;\delta'_f(s,u) = \delta'_f(s, v) + 1&amp;lt;/tex&amp;gt;. Согласно [[#lemma1|лемме]] &amp;lt;tex&amp;gt;\delta_f(s,v) \leqslant \delta'_f(s,v)&amp;lt;/tex&amp;gt;, откуда &amp;lt;tex&amp;gt;\delta'_f(s,u) = \delta'(s,v) + 1 \geqslant \delta_f(s,v) + 1 = \delta_f(s,u) + 2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итак в промежуток времени между тем, когда ребро &amp;lt;tex&amp;gt;(u,v)&amp;lt;/tex&amp;gt; становится критическим в первый раз, до момента, когда оно становится критическим в следующий раз, расстояние от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; увеличивается минимум на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. Расстояние &amp;lt;tex&amp;gt;\delta(s,u)&amp;lt;/tex&amp;gt; в начальный момент времени больше либо равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. Среди промежуточных вершин на кратчайшем пути &amp;lt;tex&amp;gt;s \leadsto u&amp;lt;/tex&amp;gt; не могут находиться &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. Следовательно к тому моменту, когда вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; станет недостижимой из источника расстояние до нее не превысит &amp;lt;tex&amp;gt;|V| - 2&amp;lt;/tex&amp;gt;. Получаем, что ребро &amp;lt;tex&amp;gt;(u, v)&amp;lt;/tex&amp;gt; могло стать критическим не более &amp;lt;tex&amp;gt;\dfrac{(|V| -2)}{2} = \dfrac{|V|}{2} - 1&amp;lt;/tex&amp;gt; раз. Поскольку в графе не более &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; пар вершин, между которыми могут существовать рёбра в остаточной сети, то общее количество критических рёбер в ходе выполнения алгоритма Эдмондса-Карпа равно &amp;lt;tex&amp;gt;O(V E)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Так как каждый увеличивающий путь содержит по крайней мере одно критическое ребро, следовательно число кратчайших путей составляет &amp;lt;tex&amp;gt;O(V E)&amp;lt;/tex&amp;gt;. На каждой итерации цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt;  рассматривается ровно один увеличивающий путь, а поскольку в случае отсутствия такого пути выполнение цикла прерывается, то число итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt;  также составляет &amp;lt;tex&amp;gt;O(V E)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Если увеличивающий путь находить поиском в ширину, то каждую итерацию цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt;  можно выполнить за время &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;. Инициализация в процедуре '''Edmonds Karp''' производится за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, следовательно время работы алгоритма алгоритма Эдмондса-Карпа составляет &amp;lt;tex&amp;gt;O(V E^2)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
== Пример графа на котором алгоритм дает плохую асимптотику ==&lt;br /&gt;
[[Файл:MaxFlowWorstCase.png|365px|thumb|right|«Грибок». Схема построения &amp;quot;сложного&amp;quot; для алгоритма Эдмондса-Карпа графа]]&lt;br /&gt;
&lt;br /&gt;
Заметим также, что существует ''сеть  грибок''&amp;lt;ref&amp;gt;[https://www.topcoder.com/community/data-science/data-science-tutorials/maximum-flow-augmenting-path-algorithms-comparison/#! Cтатья на TopCoder.com  ]&amp;lt;/ref&amp;gt; на которой нижняя граница времени работы алгоритмы Эдмондса-Карпа также составляет &amp;lt;tex&amp;gt;\Omega(V E^2)&amp;lt;/tex&amp;gt;. Рассмотрим этот случай более подробно. Норман Заде (англ. ''Norman Zadeh'') описал примеры, которые позволяют добиться асимптотики &amp;lt;tex&amp;gt;\Omega(V^3)&amp;lt;/tex&amp;gt;&amp;lt;ref&amp;gt;Norman Zadeh. Theoretical Efficiency of the Edmonds-Karp Algorithm for Computing Maximal Flows.&amp;lt;/ref&amp;gt;. В нашем примере алгоритм выполнит &amp;lt;tex&amp;gt;\Omega(V^3)&amp;lt;/tex&amp;gt; улучшений пути вне зависимости от выбора этого пути.&lt;br /&gt;
Разделим все вершины (за исключением &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;) на подмножества:&lt;br /&gt;
*&amp;lt;tex&amp;gt;S={s_1,\ldots,s_k}&amp;lt;/tex&amp;gt; — множество вершин, в которые входят рёбра из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;,&lt;br /&gt;
*&amp;lt;tex&amp;gt;T={t_1,\ldots,t_k}&amp;lt;/tex&amp;gt; — множество вершин, из которых исходят рёбра в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, &lt;br /&gt;
*&amp;lt;tex&amp;gt;U={u_1,\ldots,u_{2p}}&amp;lt;/tex&amp;gt; — множество вершин, достижимых из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; по рёбрам с бесконечной пропускной способностью (не используя иные рёбра),&lt;br /&gt;
*&amp;lt;tex&amp;gt;V={v_1,\ldots,v_{2p}}&amp;lt;/tex&amp;gt; — множество вершин, из которых можно достигнуть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; по рёбрам с бесконечной пропускной способностью (не используя иные рёбра).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; содержат &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; вершин, &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; содержат &amp;lt;tex&amp;gt;2p&amp;lt;/tex&amp;gt; вершин. Где &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; фиксированные целые числа. Каждое ребро, выделенное жирным(см. рисунок, соединяют множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;), имеет единичную пропускную способность; пунктирные рёбра имеют бесконечную пропускную способность; остальные рёбра(в форме дуги) имеют пропускную способность &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В начале работы алгоритма путь увеличиться &amp;lt;tex&amp;gt;k^2&amp;lt;/tex&amp;gt; раз по пути (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;), длина которого равна трем. После этого остаточная сеть будет содержать обратные рёбра из &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, и алгоритм выберет еще &amp;lt;tex&amp;gt;k^2&amp;lt;/tex&amp;gt; путей &amp;lt;tex&amp;gt;(s, u_1, u_2, T, S, v_2, v_1, t)&amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt;, затем путь &amp;lt;tex&amp;gt;(s, u_1, u_2, u_3, u_4, S, T, v_4, v_3, v_2, v_1, t)&amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt;11&amp;lt;/tex&amp;gt; и так далее.&lt;br /&gt;
:Число вершин в сети: &amp;lt;tex&amp;gt;n = 2\cdot k + 4\cdot p + 2&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:Число рёбер: &amp;lt;tex&amp;gt; m = k^2 + 2\cdot p\cdot k + 2\cdot k + 4\cdot p&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что число удлиняющих путей &amp;lt;tex&amp;gt; a = k^2\cdot (p+1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Возьмем &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; равным &amp;lt;tex&amp;gt;k - 1&amp;lt;/tex&amp;gt;. В этом случае &amp;lt;tex&amp;gt;n = 6 \cdot k - 2&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a = k^3&amp;lt;/tex&amp;gt;. Заде приводит более хитрые примеры с такой же асимптотикой, но они зависят от выбора пути.&lt;br /&gt;
&lt;br /&gt;
[[Файл:InGraph.png|600px|thumb|left| Изначальный граф, нулевой поток]]&lt;br /&gt;
[[Файл:SecondStage.png|600px|center|thumb| Граф после &amp;lt;tex&amp;gt;k^2&amp;lt;/tex&amp;gt; поисков пути(в нашем случае &amp;lt;tex&amp;gt;k^2 = 4&amp;lt;/tex&amp;gt;).&amp;lt;br/&amp;gt;Рёбра из между множествами &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; полностью насыщены. Поток равен четырем]]&lt;br /&gt;
[[Файл:ThirdStageEdmunds karp.png|600px|thumb|left| Алгоритм нашел путь через рёбра бесконечной вместимости, совершив еще &amp;lt;tex&amp;gt;k^2 = 4&amp;lt;/tex&amp;gt; шагов. Поток равен восьми]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Кормен, Томас Х., Лейзерсон, Чарльз И., Ривест, Рональд Л., Штайн Клиффорд'' '''Алгоритмы: построение и анализ''', 2-е издание. Пер. с англ. — М.:Издательский дом &amp;quot;Вильямс&amp;quot;, 2010. — 1296 с.: ил. — Парал. тит. англ. — ISBN 978-5-8459-0857-5 (рус.)&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/Алгоритм_Эдмондса_—_Карпа Википедия: Алгоритм Эдмондса-Карпа]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Edmonds–Karp_algorithm Википедия: Алгоритм Эдмондса-Карпа (англ.)]&lt;br /&gt;
*[https://www.topcoder.com/community/data-science/data-science-tutorials/maximum-flow-augmenting-path-algorithms-comparison/#! Статья на TopCoder.com]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63773</id>
		<title>Задача о динамической связности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63773"/>
				<updated>2018-02-17T07:51:56Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Обобщение задачи для произвольных графов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Есть [[Основные_определения:_граф,_ребро,_вершина,_степень,_петля,_путь,_цикл#Неориентированные_графы|неориентированный граф]] из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, изначально не содержащий рёбер. Требуется обработать &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; запросов трёх типов:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{add(u,v)}&amp;lt;/tex&amp;gt; {{---}} добавить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{remove(u,v)}&amp;lt;/tex&amp;gt; {{---}} удалить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{connected(u,v)}&amp;lt;/tex&amp;gt; {{---}} проверить, лежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в одной компоненте связности.&lt;br /&gt;
}}&lt;br /&gt;
== Динамическая связность в лесах ==&lt;br /&gt;
Если задача такова, что в графе нет и не может быть циклов, то она сводится к задаче о связности в [[Деревья Эйлерова обхода|деревьях эйлерова обхода]]. Время работы каждого запроса для упрощённой задачи {{---}} &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество вершин в графе.&lt;br /&gt;
&lt;br /&gt;
== Обобщение задачи для произвольных графов ==&lt;br /&gt;
&lt;br /&gt;
Существуют задачи, в которых граф не обязательно на протяжении нашей работы после каждой операции добавления ребра остаётся лесом. Для решения таких задач в каждой компоненте связности выделим [[Остовные деревья: определения, лемма о безопасном ребре|остовные деревья]], которые образуют остовный лес. &lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph.jpg|530px|thumb|left|Граф]]  [[Файл:Spanforest.jpg|530px|thumb|right|Остовный лес в графе]]&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;
&lt;br /&gt;
&lt;br /&gt;
===Проверка связности===&lt;br /&gt;
Граф и его остовный лес {{---}} одно и то же с точки зрения связности. Поэтому проверка связности в графе сводится к проверке связности в остовном лесе и решается за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&amp;lt;!--Добавление рёбер можно рассмотреть с точки зрения [[СНМ (реализация с помощью леса корневых деревьев)|системы непересекающихся множеств]], такой запрос будет работать за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Операция проверки сводится к проверке связности в остовном лесе и работает также за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Добавление ребра===&lt;br /&gt;
Чтобы разобраться с тем, как изменится граф и остовный лес при добавлении и удалении ребра, введём функцию &amp;lt;tex&amp;gt;l(e):E{\rightarrow}[0;\log n]&amp;lt;/tex&amp;gt; и назовём её ''уровнем ребра'' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;. Уровни ребра можно распределить любым способом, но для всех &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; должно выполняться следующее свойство: размер каждой компоненты связности &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;\dfrac{n}{2^i}&amp;lt;/tex&amp;gt;. Здесь графы &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; определяются так: &amp;lt;tex&amp;gt;G_i=\langle V, E\rangle: \{e \in E \mid l(e) \geqslant i\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Очевидно, что &amp;lt;tex&amp;gt;G_{\log n} \subseteq G_{\log n-1} \subseteq \ldots \subseteq G_1 \subseteq G_0 = G&amp;lt;/tex&amp;gt;. Выделим в графах остовные леса таким образом, что &amp;lt;tex&amp;gt;F_{\log n} \subseteq F_{\log n-1} \subseteq \ldots \subseteq F_1 \subseteq F_0&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt; {{---}} остовный лес графа &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Удобнее всего новому ребру давать уровень &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В этом случае изменится только &amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt;, так как в остальные подграфы &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; рёбра нулевого уровня не входят. После вставки нового ребра нам нужно проверить, были ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в одной компоненте связности до того, как мы вставили ребро. Если они лежали в разных компонентах, то необходимо новое ребро добавить и в остовный лес &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  &lt;br /&gt;
  '''function''' &amp;lt;tex&amp;gt;\mathrm{add}&amp;lt;/tex&amp;gt;('''Node''' u, '''Node''' v):&lt;br /&gt;
    '''Edge''' e = &amp;lt;tex&amp;gt;\langle &amp;lt;/tex&amp;gt;u, v&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
    e.level = 0&lt;br /&gt;
    &amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e&amp;lt;!---insert(&amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt;, e)--&amp;gt;&lt;br /&gt;
    '''if not''' &amp;lt;tex&amp;gt;\mathrm{connected(u,v)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e&amp;lt;!---insert(&amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt;, e)--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Удаление ребра===&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Если ребро, которое мы хотим удалить, не принадлежит остовному лесу, то связность между любой парой вершин сохранится.&lt;br /&gt;
|proof=Докажем от противного. Допустим, что это не так. Понятно, что при разрезании ребра нового пути между вершинами не появится.&lt;br /&gt;
Предположим, что нарушилась связность для каких-то двух вершин. Значит, мы убрали мост. А любой мост принадлежит всем остовным деревьям его компоненты. Противоречие.&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Is_there_xy.jpg|200px|thumb|right|Компонента связности T.]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, если мы удалили ребро не из остовного леса, то нам не придётся перестраивать лес и пересчитывать значение &amp;lt;tex&amp;gt;\mathrm{connected(u,v)}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим случаи, когда мы берём ребро из леса. Тогда необходимо выяснить, является ли данное ребро мостом в графе, и выполнить соответствующие действия.&lt;br /&gt;
&lt;br /&gt;
Проверим, является ли ребро мостом. У ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; известен уровень, пусть он равен &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Попробуем найти другое ребро (&amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;), соединяющее поддеревья &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_v&amp;lt;/tex&amp;gt;, на которые распалось остовное дерево исследуемой компоненты &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Если ребро &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt; существует, то его уровень не больше &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=От противного. Пусть &amp;lt;tex&amp;gt;l(xy)=j&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&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_j&amp;lt;/tex&amp;gt; (либо непосредственно ребром &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, либо каким-то другим путём). Но &amp;lt;tex&amp;gt;F_j \subseteq F_i&amp;lt;/tex&amp;gt;. Значит, в &amp;lt;tex&amp;gt;F_i&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&amp;lt;/tex&amp;gt; и появился другой путь через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Приходим к противоречию, так как в &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt; все компоненты должны быть деревьями.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чтобы найти &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, выберем из поддеревьев &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_v&amp;lt;/tex&amp;gt; наименьшее. Не умаляя общности, будем считать, что &amp;lt;tex&amp;gt;|T_u|\leqslant|T_v|&amp;lt;/tex&amp;gt;. &amp;lt;!--ежу понятно--&amp;gt; Так как всегда из двух слагаемых можно выбрать одно такое, что оно не превосходит половины их суммы, имеем важное свойство: &amp;lt;tex&amp;gt;|T_u|\leqslant\dfrac{|T_u|+|T_v|}{2}=\dfrac{|T|}{2}&amp;lt;/tex&amp;gt;. Также нам известно, что &amp;lt;tex&amp;gt;T \subseteq F_i&amp;lt;/tex&amp;gt;, а значит, &amp;lt;tex&amp;gt;|T|\leqslant\dfrac{n}{2^i}&amp;lt;/tex&amp;gt;. Отсюда &amp;lt;tex&amp;gt;|T_u|\leqslant\dfrac{n}{2^{i+1}}&amp;lt;/tex&amp;gt;. Это неравенство позволит нам увеличивать уровни рёбер при необходимости.&lt;br /&gt;
&lt;br /&gt;
Будем искать ребро &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt; следующим образом:&lt;br /&gt;
# Выбираем любое ребро уровня &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, выходящее из вершины, принадлежащей &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
# Если выбранное ребро ведёт в &amp;lt;tex&amp;gt;T_v&amp;lt;/tex&amp;gt;, выходим из цикла и добавляем ребро &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt; в остовные леса &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, для которых &amp;lt;tex&amp;gt;i\leqslant l(xy)&amp;lt;/tex&amp;gt; и выходим из цикла;&lt;br /&gt;
# Если выбранное ребро ведёт в другую вершину поддерева &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt;, увеличиваем его уровень на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;;&lt;br /&gt;
# Если есть непроверенные рёбра на интересующем нас уровне &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, переходим к пункту &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;;&lt;br /&gt;
# Если таких рёбер уровня &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; не осталось и &amp;lt;tex&amp;gt;i&amp;gt;0&amp;lt;/tex&amp;gt;, рассматриваем уровень на единицу меньший и переходим к пункту &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;;&lt;br /&gt;
# Если все рёбра просканированы и &amp;lt;tex&amp;gt;i=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; является мостом.&lt;br /&gt;
&lt;br /&gt;
'''Замечание.''' Увеличив уровень ребра на единицу, нужно не забыть обновить &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{i+1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Оценка времени работы====&lt;br /&gt;
Пункт &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; работает за &amp;lt;tex&amp;gt;O(\log^2 n)&amp;lt;/tex&amp;gt;, так как после выхода из цикла мы добавляем ребро за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; на каждом уровне, а количество уровней не больше &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;!--5 сек, тут кажись я права всё-таки, нужен Лёха--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть до момента, когда мы нашли нужное ребро, мы сделали &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; неудачных сканирований. После каждого такого сканирования нам приходится добавлять новые рёбра в &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt;, что стоит &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Получаем сложность удаления одного ребра &amp;lt;tex&amp;gt;O(\log^2{n}+S\cdot\log n)&amp;lt;/tex&amp;gt;. &amp;lt;!--- Возможно, мы удалим мост, но это уже другая история, да и она всяко лучше логарифмов в квадрате... ---&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выразим сложность одной операции &amp;lt;tex&amp;gt;\mathrm{remove}&amp;lt;/tex&amp;gt; другим способом. Для &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; вызовов процедуры сложность равна &amp;lt;tex&amp;gt;O(\log^2{n}\cdot m+\log n\cdot\displaystyle \sum_{i=1}^m S_i)&amp;lt;/tex&amp;gt;, что не превосходит &amp;lt;tex&amp;gt;O(\log^2{n} \cdot m+\log n\cdot\log n\cdot m)&amp;lt;/tex&amp;gt;, так как уровень ребра &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; раз рос максимум до &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;. Отсюда суммарная сложность всех запросов равна &amp;lt;tex&amp;gt;O(\log^2{n}\cdot m)&amp;lt;/tex&amp;gt;, а для одного запроса мы решаем задачу за &amp;lt;tex&amp;gt;O(\log^2{n})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
  '''function''' &amp;lt;tex&amp;gt;\mathrm{remove}&amp;lt;/tex&amp;gt;('''Node''' u, '''Node''' v):&lt;br /&gt;
    '''Edge''' e = &amp;lt;tex&amp;gt;\langle &amp;lt;/tex&amp;gt;u, v&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' i = e.level '''downto''' 0&lt;br /&gt;
      &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;G_i\setminus&amp;lt;/tex&amp;gt;e&amp;lt;!---delete(&amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt;, e)---&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;F_i\setminus&amp;lt;/tex&amp;gt;e&amp;lt;!---delete(&amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, e)---&amp;gt;&lt;br /&gt;
      '''Edge''' e2&lt;br /&gt;
      '''for''' e2 = &amp;lt;tex&amp;gt;\langle &amp;lt;/tex&amp;gt;x, y&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt; : e2.level == i '''and''' x &amp;lt;tex&amp;gt;\in T_u&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' y &amp;lt;tex&amp;gt;\in T_v&amp;lt;/tex&amp;gt; &lt;br /&gt;
          '''for''' j = i '''downto''' 0&lt;br /&gt;
            &amp;lt;tex&amp;gt;F_j&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;F_j&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e2&amp;lt;!---insert(&amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, e2)--&amp;gt;&lt;br /&gt;
          '''return'''&lt;br /&gt;
        '''else''' &lt;br /&gt;
          e2.level++&lt;br /&gt;
          &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e2&amp;lt;!---insert(&amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, e2)--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Деревья Эйлерова обхода|Деревья эйлерова обхода]]&lt;br /&gt;
* [[Задача о динамической связности оффлайн]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Dynamic_connectivity Dynamic connectivity {{---}} Википедия]&lt;br /&gt;
* [http://numeralis.ru/algoritmyi-i-strukturyi-dannyih-poiska-dinamicheskaya-svyaznost-v-grafah-babenko-maksim/ Лекции {{---}} Академия Яндекса]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Связность в графах]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63772</id>
		<title>Задача о динамической связности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63772"/>
				<updated>2018-02-17T07:50:44Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Обобщение задачи для произвольных графов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Есть [[Основные_определения:_граф,_ребро,_вершина,_степень,_петля,_путь,_цикл#Неориентированные_графы|неориентированный граф]] из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, изначально не содержащий рёбер. Требуется обработать &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; запросов трёх типов:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{add(u,v)}&amp;lt;/tex&amp;gt; {{---}} добавить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{remove(u,v)}&amp;lt;/tex&amp;gt; {{---}} удалить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{connected(u,v)}&amp;lt;/tex&amp;gt; {{---}} проверить, лежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в одной компоненте связности.&lt;br /&gt;
}}&lt;br /&gt;
== Динамическая связность в лесах ==&lt;br /&gt;
Если задача такова, что в графе нет и не может быть циклов, то она сводится к задаче о связности в [[Деревья Эйлерова обхода|деревьях эйлерова обхода]]. Время работы каждого запроса для упрощённой задачи {{---}} &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество вершин в графе.&lt;br /&gt;
&lt;br /&gt;
== Обобщение задачи для произвольных графов ==&lt;br /&gt;
&lt;br /&gt;
Существуют задачи, в которых граф не обязательно на протяжении нашей работы после каждой операции добавления ребра остаётся лесом. Для решения таких задач в каждой компоненте связности выделим [[Остовные деревья: определения, лемма о безопасном ребре|остовные деревья]], которые образуют остовный лес. &lt;br /&gt;
&lt;br /&gt;
[[Файл:Graph.jpg|530px|thumb|left|Граф]]  [[Файл:Spanforest.jpg|530px|thumb|right|Остовный лес в графе]]&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;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Проверка связности===&lt;br /&gt;
Граф и его остовный лес {{---}} одно и то же с точки зрения связности. Поэтому проверка связности в графе сводится к проверке связности в остовном лесе и решается за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&amp;lt;!--Добавление рёбер можно рассмотреть с точки зрения [[СНМ (реализация с помощью леса корневых деревьев)|системы непересекающихся множеств]], такой запрос будет работать за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Операция проверки сводится к проверке связности в остовном лесе и работает также за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Добавление ребра===&lt;br /&gt;
Чтобы разобраться с тем, как изменится граф и остовный лес при добавлении и удалении ребра, введём функцию &amp;lt;tex&amp;gt;l(e):E{\rightarrow}[0;\log n]&amp;lt;/tex&amp;gt; и назовём её ''уровнем ребра'' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;. Уровни ребра можно распределить любым способом, но для всех &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; должно выполняться следующее свойство: размер каждой компоненты связности &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;\dfrac{n}{2^i}&amp;lt;/tex&amp;gt;. Здесь графы &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; определяются так: &amp;lt;tex&amp;gt;G_i=\langle V, E\rangle: \{e \in E \mid l(e) \geqslant i\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Очевидно, что &amp;lt;tex&amp;gt;G_{\log n} \subseteq G_{\log n-1} \subseteq \ldots \subseteq G_1 \subseteq G_0 = G&amp;lt;/tex&amp;gt;. Выделим в графах остовные леса таким образом, что &amp;lt;tex&amp;gt;F_{\log n} \subseteq F_{\log n-1} \subseteq \ldots \subseteq F_1 \subseteq F_0&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt; {{---}} остовный лес графа &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Удобнее всего новому ребру давать уровень &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В этом случае изменится только &amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt;, так как в остальные подграфы &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; рёбра нулевого уровня не входят. После вставки нового ребра нам нужно проверить, были ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в одной компоненте связности до того, как мы вставили ребро. Если они лежали в разных компонентах, то необходимо новое ребро добавить и в остовный лес &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
  &lt;br /&gt;
  '''function''' &amp;lt;tex&amp;gt;\mathrm{add}&amp;lt;/tex&amp;gt;('''Node''' u, '''Node''' v):&lt;br /&gt;
    '''Edge''' e = &amp;lt;tex&amp;gt;\langle &amp;lt;/tex&amp;gt;u, v&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
    e.level = 0&lt;br /&gt;
    &amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e&amp;lt;!---insert(&amp;lt;tex&amp;gt;G_0&amp;lt;/tex&amp;gt;, e)--&amp;gt;&lt;br /&gt;
    '''if not''' &amp;lt;tex&amp;gt;\mathrm{connected(u,v)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e&amp;lt;!---insert(&amp;lt;tex&amp;gt;F_0&amp;lt;/tex&amp;gt;, e)--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Удаление ребра===&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Если ребро, которое мы хотим удалить, не принадлежит остовному лесу, то связность между любой парой вершин сохранится.&lt;br /&gt;
|proof=Докажем от противного. Допустим, что это не так. Понятно, что при разрезании ребра нового пути между вершинами не появится.&lt;br /&gt;
Предположим, что нарушилась связность для каких-то двух вершин. Значит, мы убрали мост. А любой мост принадлежит всем остовным деревьям его компоненты. Противоречие.&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Is_there_xy.jpg|200px|thumb|right|Компонента связности T.]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, если мы удалили ребро не из остовного леса, то нам не придётся перестраивать лес и пересчитывать значение &amp;lt;tex&amp;gt;\mathrm{connected(u,v)}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим случаи, когда мы берём ребро из леса. Тогда необходимо выяснить, является ли данное ребро мостом в графе, и выполнить соответствующие действия.&lt;br /&gt;
&lt;br /&gt;
Проверим, является ли ребро мостом. У ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; известен уровень, пусть он равен &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Попробуем найти другое ребро (&amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;), соединяющее поддеревья &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_v&amp;lt;/tex&amp;gt;, на которые распалось остовное дерево исследуемой компоненты &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Если ребро &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt; существует, то его уровень не больше &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=От противного. Пусть &amp;lt;tex&amp;gt;l(xy)=j&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&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_j&amp;lt;/tex&amp;gt; (либо непосредственно ребром &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, либо каким-то другим путём). Но &amp;lt;tex&amp;gt;F_j \subseteq F_i&amp;lt;/tex&amp;gt;. Значит, в &amp;lt;tex&amp;gt;F_i&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&amp;lt;/tex&amp;gt; и появился другой путь через &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;. Приходим к противоречию, так как в &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt; все компоненты должны быть деревьями.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Чтобы найти &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt;, выберем из поддеревьев &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_v&amp;lt;/tex&amp;gt; наименьшее. Не умаляя общности, будем считать, что &amp;lt;tex&amp;gt;|T_u|\leqslant|T_v|&amp;lt;/tex&amp;gt;. &amp;lt;!--ежу понятно--&amp;gt; Так как всегда из двух слагаемых можно выбрать одно такое, что оно не превосходит половины их суммы, имеем важное свойство: &amp;lt;tex&amp;gt;|T_u|\leqslant\dfrac{|T_u|+|T_v|}{2}=\dfrac{|T|}{2}&amp;lt;/tex&amp;gt;. Также нам известно, что &amp;lt;tex&amp;gt;T \subseteq F_i&amp;lt;/tex&amp;gt;, а значит, &amp;lt;tex&amp;gt;|T|\leqslant\dfrac{n}{2^i}&amp;lt;/tex&amp;gt;. Отсюда &amp;lt;tex&amp;gt;|T_u|\leqslant\dfrac{n}{2^{i+1}}&amp;lt;/tex&amp;gt;. Это неравенство позволит нам увеличивать уровни рёбер при необходимости.&lt;br /&gt;
&lt;br /&gt;
Будем искать ребро &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt; следующим образом:&lt;br /&gt;
# Выбираем любое ребро уровня &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, выходящее из вершины, принадлежащей &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt;. &lt;br /&gt;
# Если выбранное ребро ведёт в &amp;lt;tex&amp;gt;T_v&amp;lt;/tex&amp;gt;, выходим из цикла и добавляем ребро &amp;lt;tex&amp;gt;xy&amp;lt;/tex&amp;gt; в остовные леса &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, для которых &amp;lt;tex&amp;gt;i\leqslant l(xy)&amp;lt;/tex&amp;gt; и выходим из цикла;&lt;br /&gt;
# Если выбранное ребро ведёт в другую вершину поддерева &amp;lt;tex&amp;gt;T_u&amp;lt;/tex&amp;gt;, увеличиваем его уровень на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;;&lt;br /&gt;
# Если есть непроверенные рёбра на интересующем нас уровне &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, переходим к пункту &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;;&lt;br /&gt;
# Если таких рёбер уровня &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; не осталось и &amp;lt;tex&amp;gt;i&amp;gt;0&amp;lt;/tex&amp;gt;, рассматриваем уровень на единицу меньший и переходим к пункту &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;;&lt;br /&gt;
# Если все рёбра просканированы и &amp;lt;tex&amp;gt;i=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; является мостом.&lt;br /&gt;
&lt;br /&gt;
'''Замечание.''' Увеличив уровень ребра на единицу, нужно не забыть обновить &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{i+1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Оценка времени работы====&lt;br /&gt;
Пункт &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; работает за &amp;lt;tex&amp;gt;O(\log^2 n)&amp;lt;/tex&amp;gt;, так как после выхода из цикла мы добавляем ребро за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; на каждом уровне, а количество уровней не больше &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;!--5 сек, тут кажись я права всё-таки, нужен Лёха--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть до момента, когда мы нашли нужное ребро, мы сделали &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; неудачных сканирований. После каждого такого сканирования нам приходится добавлять новые рёбра в &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt;, что стоит &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Получаем сложность удаления одного ребра &amp;lt;tex&amp;gt;O(\log^2{n}+S\cdot\log n)&amp;lt;/tex&amp;gt;. &amp;lt;!--- Возможно, мы удалим мост, но это уже другая история, да и она всяко лучше логарифмов в квадрате... ---&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выразим сложность одной операции &amp;lt;tex&amp;gt;\mathrm{remove}&amp;lt;/tex&amp;gt; другим способом. Для &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; вызовов процедуры сложность равна &amp;lt;tex&amp;gt;O(\log^2{n}\cdot m+\log n\cdot\displaystyle \sum_{i=1}^m S_i)&amp;lt;/tex&amp;gt;, что не превосходит &amp;lt;tex&amp;gt;O(\log^2{n} \cdot m+\log n\cdot\log n\cdot m)&amp;lt;/tex&amp;gt;, так как уровень ребра &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; раз рос максимум до &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;. Отсюда суммарная сложность всех запросов равна &amp;lt;tex&amp;gt;O(\log^2{n}\cdot m)&amp;lt;/tex&amp;gt;, а для одного запроса мы решаем задачу за &amp;lt;tex&amp;gt;O(\log^2{n})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&lt;br /&gt;
  '''function''' &amp;lt;tex&amp;gt;\mathrm{remove}&amp;lt;/tex&amp;gt;('''Node''' u, '''Node''' v):&lt;br /&gt;
    '''Edge''' e = &amp;lt;tex&amp;gt;\langle &amp;lt;/tex&amp;gt;u, v&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' i = e.level '''downto''' 0&lt;br /&gt;
      &amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;G_i\setminus&amp;lt;/tex&amp;gt;e&amp;lt;!---delete(&amp;lt;tex&amp;gt;G_i&amp;lt;/tex&amp;gt;, e)---&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;F_i\setminus&amp;lt;/tex&amp;gt;e&amp;lt;!---delete(&amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, e)---&amp;gt;&lt;br /&gt;
      '''Edge''' e2&lt;br /&gt;
      '''for''' e2 = &amp;lt;tex&amp;gt;\langle &amp;lt;/tex&amp;gt;x, y&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt; : e2.level == i '''and''' x &amp;lt;tex&amp;gt;\in T_u&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' y &amp;lt;tex&amp;gt;\in T_v&amp;lt;/tex&amp;gt; &lt;br /&gt;
          '''for''' j = i '''downto''' 0&lt;br /&gt;
            &amp;lt;tex&amp;gt;F_j&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;F_j&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e2&amp;lt;!---insert(&amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, e2)--&amp;gt;&lt;br /&gt;
          '''return'''&lt;br /&gt;
        '''else''' &lt;br /&gt;
          e2.level++&lt;br /&gt;
          &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;G_{i+1}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; e2&amp;lt;!---insert(&amp;lt;tex&amp;gt;F_i&amp;lt;/tex&amp;gt;, e2)--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Деревья Эйлерова обхода|Деревья эйлерова обхода]]&lt;br /&gt;
* [[Задача о динамической связности оффлайн]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Dynamic_connectivity Dynamic connectivity {{---}} Википедия]&lt;br /&gt;
* [http://numeralis.ru/algoritmyi-i-strukturyi-dannyih-poiska-dinamicheskaya-svyaznost-v-grafah-babenko-maksim/ Лекции {{---}} Академия Яндекса]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Связность в графах]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D1%8F%D0%BC%D0%B1%D0%B4%D0%B0-%D0%B8%D1%81%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=63682</id>
		<title>Лямбда-исчисление</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D1%8F%D0%BC%D0%B1%D0%B4%D0%B0-%D0%B8%D1%81%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=63682"/>
				<updated>2018-01-29T01:50:03Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* β-редукция */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nohate}}&lt;br /&gt;
'''Лямбда-исчисление''' (''англ. lambda calculus'') {{---}} формальная система, придуманная в 1930-х годах &lt;br /&gt;
Алонзо Чёрчем. Лямбда-функция является, по сути, анонимной функцией.&lt;br /&gt;
Эта концепция показала себя удобной и сейчас активно используется во многих&lt;br /&gt;
языках программирования.&lt;br /&gt;
&lt;br /&gt;
== Лямбда-исчисление==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Лямбда-выражением''' (англ. &amp;lt;tex&amp;gt;\lambda&amp;lt;/tex&amp;gt;''-term'') называется выражение, удовлетворяющее следующей грамматике:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
\Lambda \to V\\&lt;br /&gt;
\Lambda \to \Lambda \ \Lambda\\&lt;br /&gt;
\Lambda \to \lambda V . \Lambda&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} множество всех строк над фиксированным алфавитом &amp;lt;tex&amp;gt; \Sigma \setminus \{ &amp;quot;\lambda&amp;quot;, &amp;quot;\ &amp;quot;,\ &amp;quot;.&amp;quot;\} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Пробел во втором правиле является терминалом грамматики. Иногда его обозначают как @, чтобы он не сливался с другими символами в выражении.&lt;br /&gt;
&lt;br /&gt;
В первом случае функция является просто переменной. &lt;br /&gt;
Во втором происходит ''аппликация'' (''применение'') одной функции к другой.&lt;br /&gt;
Это аналогично вычислению функции-левого операнда на аргументе-правом операнде.&lt;br /&gt;
В третьем {{---}} ''абстракция'' по переменной. В данном случае происходит &lt;br /&gt;
создание функции одного аргумента с заданными именем аргумента и телом функции.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим, например, &amp;lt;tex&amp;gt;\lambda&amp;lt;/tex&amp;gt;-терм &amp;lt;tex&amp;gt;\operatorname{id} = \lambda x\ .\ x&amp;lt;/tex&amp;gt;. Эта функция принимает аргумент и &lt;br /&gt;
возвращает его неизменённым. Например, &lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{id}\ 2 \equiv 2&amp;lt;/tex&amp;gt;. Аналогично, &amp;lt;tex&amp;gt;\operatorname{id}\ y \equiv y&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Еще примеры:&lt;br /&gt;
:&amp;lt;tex&amp;gt;&lt;br /&gt;
x\\&lt;br /&gt;
(x\ z)\\&lt;br /&gt;
(\lambda x.(x\ z))\\&lt;br /&gt;
(\lambda z.(\lambda w.((\lambda y.((\lambda x.(x\ z))\ y))\ w)))\\&lt;br /&gt;
 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Иногда &amp;lt;tex&amp;gt;\lambda&amp;lt;/tex&amp;gt; -термы пишут по другому. Для краткости подряд идущие лямбды заменяют на одну. Например:&lt;br /&gt;
:&amp;lt;tex&amp;gt;\lambda x\ .\ \lambda y\ .P\ \to\ \lambda xy.P&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
===Приоритет операций===&lt;br /&gt;
* Аппликация: &amp;lt;tex&amp;gt;x\ y\ z\ w \equiv ((x\ y)\ z)\ w&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Абстракция забирает себе всё, до чего дотянется: &amp;lt;tex&amp;gt;\lambda x\ .\ \lambda y\ .\ \lambda z\ .\ z\ y\ x \equiv \lambda x\ .\ (\lambda y\ .\ (\lambda z\ .\ ((z\ y)\ x)))&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;
Например, в &amp;lt;tex&amp;gt;\lambda x\ .\ y\ x&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;\lambda y\ .\ x\ (\lambda x\ .\ x)&amp;lt;/tex&amp;gt;&lt;br /&gt;
в своём первом вхождении переменная &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; свободна, а во втором {{---}} связана.&lt;br /&gt;
&lt;br /&gt;
Связанные переменные {{---}} это аргументы функции. То есть для функции они являются локальными.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим функции &amp;lt;tex&amp;gt;\lambda y\ .\ y&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\lambda x\ .\ y&amp;lt;/tex&amp;gt;. В первой из них при взгляде на &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;&lt;br /&gt;
понятно, что она имеет отношение к переменной, по которой производилась &lt;br /&gt;
абстракция. Если по одной и той же&lt;br /&gt;
переменной абстракция производилась более одного раза, то переменная связана&lt;br /&gt;
с самым поздним (самым нижним в дереве разбора) абстрагированием. Например, в&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda x\ .\ \lambda x\ .\ \lambda y\ .\ \lambda x\ .\ x&amp;lt;/tex&amp;gt;, переменная &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; связана с самой правой абстракцией &lt;br /&gt;
по &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===α-эквивалетность===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''&amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-эквивалетностью''' (англ. ''&amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; -equivalence'') {{---}} называется наименьшее соотношение эквивалентности на &amp;lt;tex&amp;gt;\Lambda&amp;lt;/tex&amp;gt; такое что:&lt;br /&gt;
:&amp;lt;tex&amp;gt;P=_\alpha P&amp;lt;/tex&amp;gt; для любого &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;\lambda x.P=_\alpha \lambda y.P[x:=y]&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;y \not\in FV(P)&amp;lt;/tex&amp;gt;&lt;br /&gt;
и замкнуто относительно следующих правил:&lt;br /&gt;
:&amp;lt;tex&amp;gt; P=_\alpha P' \Rightarrow \forall x \in V: \lambda x.P=_\alpha \lambda x.P'\\&lt;br /&gt;
P=_\alpha P' \Rightarrow \forall Z \in \Lambda : P Z =_\alpha P'Z\\&lt;br /&gt;
P=_\alpha P' \Rightarrow \forall Z \in \Lambda : Z P =_\alpha Z P'\\&lt;br /&gt;
P=_\alpha P' \Rightarrow P'=_\alpha P\\&lt;br /&gt;
P=_\alpha P' \ \&amp;amp; \ P'=_\alpha P'' \Rightarrow P=_\alpha P''\\&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Функции &amp;lt;tex&amp;gt;\lambda x\ .\ \lambda y\ .\ x\ y\ z&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\lambda a\ .\ \lambda x\ .\ a\ x\ z&amp;lt;/tex&amp;gt; являются &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-эквивалентными,&lt;br /&gt;
а &amp;lt;tex&amp;gt;\lambda x\ .\ \lambda y\ .\ y\ z&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\lambda y\ .\ \lambda x\ .\ y\ z&amp;lt;/tex&amp;gt; {{---}} нет.&lt;br /&gt;
&lt;br /&gt;
===β-редукция===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''&amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукция''' (англ. ''&amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; -reduction'') {{---}} это наименьшее соотношение на &amp;lt;tex&amp;gt;\Lambda&amp;lt;/tex&amp;gt; такое что&lt;br /&gt;
:&amp;lt;tex&amp;gt;(\lambda x.P)Q\to _\beta P[x:=Q]&amp;lt;/tex&amp;gt;&lt;br /&gt;
и замкнуто относительно следующих правил&lt;br /&gt;
:&amp;lt;tex&amp;gt;P\to _\beta P' \Rightarrow \forall x\in V:\lambda x.P\to _\beta \lambda x.P'\\&lt;br /&gt;
P\to _\beta P' \Rightarrow \forall Z\in \Lambda : P\ Z\to _\beta P'\ Z\\&lt;br /&gt;
P\to _\beta P' \Rightarrow \forall Z\in \Lambda : Z\ P\to _\beta Z\ P'&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;f \to_\beta g&amp;lt;/tex&amp;gt; обозначают сведение &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; к &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; с помощью одной &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукции.&lt;br /&gt;
А через &amp;lt;tex&amp;gt;f \to_\beta^* g&amp;lt;/tex&amp;gt; {{---}} за ноль или более.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
В &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукции вполне возможна функция вида &amp;lt;tex&amp;gt;\lambda x. \lambda x.x&amp;lt;/tex&amp;gt;. Во время подстановки вместо &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; внутренняя переменная не заменяется - действует принцип локальной переменной. Но принято считать, что таких ситуаций не возникает и все переменные называются разными именами.&lt;br /&gt;
&lt;br /&gt;
===Каррирование===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Каррирование''' (англ. ''carrying'') {{---}} преобразование функции от многих переменных в функцию, берущую свои аргументы по одному. Для функции &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; типа &amp;lt;tex&amp;gt;h\ :\ (A\ *\ B)\ \to\ C&amp;lt;/tex&amp;gt; оператор каррирования &amp;lt;tex&amp;gt;\Lambda &amp;lt;/tex&amp;gt; выполняет преобразование &amp;lt;tex&amp;gt;\Lambda (h)\ :\ A\to (B\to C)&amp;lt;/tex&amp;gt;. Таким образом &amp;lt;tex&amp;gt;\Lambda (h)&amp;lt;/tex&amp;gt; берет аргумент типа &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и возвращает функцию типа &amp;lt;tex&amp;gt;B\ \to\ C&amp;lt;/tex&amp;gt;. С интуитивной точки зрения, каррирование функции позволяет фиксировать ее некоторый аргумент, возвращая функцию от остальных аргументов. Таким образом, &amp;lt;tex&amp;gt;\Lambda&amp;lt;/tex&amp;gt; представляет собой функцию типа &amp;lt;tex&amp;gt;\Lambda :\ (A\ *\ B\to C)\to (A\to (B\to C))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Нотация Де Брауна==&lt;br /&gt;
Существует также альтернативное эквивалентное определение &amp;lt;tex&amp;gt;\lambda&amp;lt;/tex&amp;gt;-исчисления.&lt;br /&gt;
В оригинальном определении для обозначения переменных использовались имена,&lt;br /&gt;
и была проблема с тем, что не были запрещены одинаковые имена в разных&lt;br /&gt;
абстракциях. &lt;br /&gt;
&lt;br /&gt;
От этой проблемы можно избавиться следующим образом. Вместо имени переменной &lt;br /&gt;
будет храниться натуральное число {{---}} количество абстракций в дереве разбора,&lt;br /&gt;
на которое нужно подняться, чтобы найти ту лямбду, с которой данная переменная &lt;br /&gt;
связана. В данной нотации получаются несколько более простые определения &lt;br /&gt;
свободных переменных и &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукции. &lt;br /&gt;
&lt;br /&gt;
Грамматику нотации можно задать как:&lt;br /&gt;
:&amp;lt;tex&amp;gt;e\ ::= n\ |\ \lambda .e\ |\ e\ e&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примеры выражений в этой нотации:&lt;br /&gt;
:&amp;lt;tex&amp;gt;&lt;br /&gt;
\begin{tabular}{cc}&lt;br /&gt;
Standart &amp;amp; de Bruijn \\&lt;br /&gt;
$\lambda x.x$ &amp;amp; $\lambda .0$ \\&lt;br /&gt;
$\lambda z.z$ &amp;amp; $\lambda .0$ \\&lt;br /&gt;
$\lambda x. \lambda y.x$ &amp;amp; $\lambda . \lambda .1$\\&lt;br /&gt;
$\lambda x. \lambda y. \lambda s. \lambda z.x\ s\ (y\ s\ z)$ &amp;amp; $\lambda . \lambda . \lambda . \lambda .3\ 1(2\ 1\ 0)$\\&lt;br /&gt;
$(\lambda x.x\ x)(\lambda x.x\ x)$ &amp;amp; $(\lambda .0\ 0)(\lambda .0\ 0)$\\&lt;br /&gt;
$(\lambda x. \lambda x.x)(\lambda y.y)$ &amp;amp; $(\lambda .\lambda .0)(\lambda .0)$\\&lt;br /&gt;
\end{tabular}&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Переменная называется свободной, если ей соответствует число, которое больше&lt;br /&gt;
количества абстракций на пути до неё в дереве разбора.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукции же нужно будет ко всем свободным переменным заменяющего &lt;br /&gt;
дерева при каждой замене прибавить число, равное разницы уровней раньше и сейчас.&lt;br /&gt;
Это будет соответствовать тому, что эта переменная продолжит «держаться» за&lt;br /&gt;
ту же лямбду, что и раньше.&lt;br /&gt;
&lt;br /&gt;
==Нумералы Чёрча и программирование на &amp;lt;tex&amp;gt;\lambda&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;
:&amp;lt;tex&amp;gt;\bar 0 = \lambda s\ .\ \lambda z\ .\ z&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;\bar 1 = \lambda s\ .\ \lambda z\ .\ s\ z&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;\bar 2 = \lambda s\ .\ \lambda z\ .\ s\ (s\ z)&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;\bar 3 = \lambda s\ .\ \lambda z\ .\ s\ (s\ (s\ z))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Каждое число будет функцией двух аргументов: какой-то функции и начального значения.&lt;br /&gt;
Число &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз применять функцию к начальному значению и возвращать &lt;br /&gt;
результат. Если такому &amp;quot;числу&amp;quot; дать на вход функцию &amp;lt;tex&amp;gt;(+1)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; в качестве &lt;br /&gt;
начального значения, то на выходе как раз будет ожидаемое от функции число:&lt;br /&gt;
&amp;lt;tex&amp;gt;\bar 3\ (+1)\ 0 \equiv 3&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===+1===&lt;br /&gt;
Функция, прибавляющая 1 к числу, должна принимать первым аргументом число.&lt;br /&gt;
Но число {{---}} функция двух аргументов. Значит, эта функция должна принимать три&lt;br /&gt;
аргумента: &amp;quot;число&amp;quot; &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, которое хочется увеличить, функция, которую надо будет&lt;br /&gt;
&amp;lt;tex&amp;gt;n+1&amp;lt;/tex&amp;gt; раз применить, и начальное значение.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{succ} = \lambda n\ .\ \lambda s\ .\ \lambda z\ .\ s\ (n\ s\ z)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;tex&amp;gt;n\ s\ z&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз применённая к &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt; функция &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Но нужно применить &amp;lt;tex&amp;gt;n+1&amp;lt;/tex&amp;gt; &lt;br /&gt;
раз. Отсюда &amp;lt;tex&amp;gt;s\ (n\ s\ z)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Сложение===&lt;br /&gt;
Сложение двух чисел похоже на прибавление единицы. Но только надо прибавить не единицу, а второе число.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{plus} = \lambda n\ .\ \lambda m\ .\ \lambda s\ .\ \lambda z\ .\ n\ s\ (m\ s\ z)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз применить &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; к применённому &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; раз &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; к &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(\operatorname{plus}\ \bar 3\ \bar 3)\ (+1)\ 0 \equiv 6&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(\operatorname{plus}\ ((\operatorname{plus}\ 2\ 5)(+1)\ 0)\ 4)(+1)0 \equiv 11&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
===Умножение===&lt;br /&gt;
Умножение похоже на сложение, но прибавлять надо не единицу, а второе число.&lt;br /&gt;
Или, в терминах нумералов Чёрча, в качестве применяемой несколько раз&lt;br /&gt;
функции должна быть не &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, а функция, применяющая &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{mult} = \lambda n\ .\ \lambda m\ .\ \lambda s\ .\ \lambda z\ .\ n\ (m\ s)\ z&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;tex&amp;gt;m\ s&amp;lt;/tex&amp;gt; {{---}} функция, которая &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; раз применит &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; к тому, что дадут ей на &lt;br /&gt;
вход. С помощью &amp;lt;tex&amp;gt;\eta&amp;lt;/tex&amp;gt;-редукции можно немного сократить эту формулу&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{mult} = \lambda n\ .\ \lambda m\ .\ \lambda s\ .\ n\ (m\ s)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(\operatorname{mult} \bar 3\ \bar 3)\ (+1)\ 0 \equiv 9&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Возведение в степень===&lt;br /&gt;
It's a kind of magic&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{power} = \lambda n\ .\ \lambda m\ .\ \lambda s\ .\ \lambda z\ .\ m\ n\ s\ z&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(\operatorname{power}\ \bar 3\ (\operatorname{succ}\ \bar 3))\ (+1)\ 0 \equiv 81&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Логические значения===&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{true} = \lambda a\ .\ \lambda b\ .\ a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{false} = \lambda a\ .\ \lambda b\ .\ b&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функции двух аргументов, возвращающие первый и второй, соответственное, аргументы.&lt;br /&gt;
Забавный факт: &amp;lt;tex&amp;gt;\operatorname{false} \equiv_\alpha \operatorname{zero}&amp;lt;/tex&amp;gt;. Эти функции сделаны такими для того, &lt;br /&gt;
чтобы красиво написать функцию &amp;lt;tex&amp;gt;\operatorname{if}&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{if} = \lambda p\ .\ \lambda t\ .\ \lambda e\ .\ p\ t\ e&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если ей в качестве первого аргумента дадут &amp;lt;tex&amp;gt;\operatorname{true}&amp;lt;/tex&amp;gt;, то вернётся &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, иначе {{---}} &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Стандартные функции булевой логики:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{and} = \lambda n\ .\ \lambda m\ .\ \operatorname{if}\ n\ m\ \operatorname{false}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{or} = \lambda n\ .\ \lambda m\ .\ \operatorname{if}\ n\ \operatorname{true} \  m&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{not} = \lambda b\ .\ \operatorname{if}\ b\ \operatorname{false} \ \operatorname{true}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ещё одной важной функцией является функция проверки, является ли число нулём:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{isZero} = \lambda n\ .\ n\ (\lambda c\ .\ \operatorname{false})\ \operatorname{true}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция выглядит несколько странно. &amp;lt;tex&amp;gt;\lambda c \to \operatorname{false}&amp;lt;/tex&amp;gt; - функция, которая независимо&lt;br /&gt;
от того, что ей дали на вход, возвращает &amp;lt;tex&amp;gt;\operatorname{false}&amp;lt;/tex&amp;gt;. Тогда, если в качестве &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
будет дан ноль, то функция, по определению нуля, не выполнится ни разу, и будет&lt;br /&gt;
возвращено значение по умолчанию &amp;lt;tex&amp;gt;\operatorname{true}&amp;lt;/tex&amp;gt;. Иначе же функция будет запущено, и &lt;br /&gt;
вернётся &amp;lt;tex&amp;gt;\operatorname{false}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пара===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{pair} = \lambda a\ .\ \lambda b\ .\ \lambda t\ .\ t\ a\ b&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{fst} = \lambda p\ .\ p\ \operatorname{true}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{snd} = \lambda p\ .\ p\ \operatorname{false}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция &amp;lt;tex&amp;gt;\operatorname{pair}&amp;lt;/tex&amp;gt; принимает два значения и запаковывает их в пару так, чтобы к ним можно было обращаться по &amp;lt;tex&amp;gt;\operatorname{fst}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\operatorname{snd}&amp;lt;/tex&amp;gt;. В &amp;lt;tex&amp;gt;\operatorname{fst}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\operatorname{snd}&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\operatorname{pair}&amp;lt;/tex&amp;gt; будет подставлено &amp;lt;tex&amp;gt;\operatorname{true}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\operatorname{false}&amp;lt;/tex&amp;gt;, возвращающие, соответственно, первый и второй аргументы, то есть &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;, соответственно.&lt;br /&gt;
&lt;br /&gt;
===Вычитание===&lt;br /&gt;
В отличие от всех предыдущих функций, вычитание для натуральных чисел определено только в случае, если уменьшаемое больше вычитаемого. Положим в противном случае результат равным нулю. Пусть уже есть функция, которая вычитает из числа единицу. Тогда на её основе легко сделать, собственно, вычитание.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{minus} = \lambda n\ .\ \lambda m\ .\ m\ \operatorname{pred} n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это то же самое, что &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; раз вычесть единицу из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Осталось, собственно, функция для вычитания единицы. Однако, это не так просто, как может показаться на первый взгляд. Проблема в том, что, имея функцию, которую нужно применить для того, чтобы продвинуться вперёд, продвинуться назад будет проблематично. Если попробовать воспользоваться идеей о том, чтобы, начав от нуля, идти вперёд, и пройти на один шаг меньше, то будет не очень понятно, как же остановиться ровно за один шаг до конца. Для реализации вычитания единицы сделаем следующее. &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз выполним следующее: имея пару &amp;lt;tex&amp;gt;\langle n-1, n-2\rangle&amp;lt;/tex&amp;gt; построим пару &amp;lt;tex&amp;gt;\langle n, n-1\rangle&amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; шагов во втором элементе пары будет записано число &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt;, которое и хочется получить. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{pred} = \lambda n\ .\ \lambda s\ .\ \lambda z.\ \operatorname{snd}\ (&lt;br /&gt;
   n\ (&lt;br /&gt;
          \lambda p\ .\ \operatorname{pair}\ (s\ (\operatorname{fst} p))\ (\operatorname{fst} p)&lt;br /&gt;
     )\ (\operatorname{pair}\ z\ z))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если вы ничего не поняли, не огорчайтесь. Вычитание придумал Клини, когда ему вырывали зуб мудрости. А сейчас наркоз уже не тот.&lt;br /&gt;
&lt;br /&gt;
===Сравнение===&lt;br /&gt;
Так как вычитание определено таким способом, чтобы для случая, в котором уменьшаемое больше, чем вычитаемое, возвращать ноль, можно определить сравнение на больше-меньше через него. Равными же числа &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считаются, если &amp;lt;tex&amp;gt;a - b = 0 \wedge b - a = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{le} = \lambda n\ .\ \lambda m\ .\ \operatorname{isZero}\ (\operatorname{minus}\ n\ m)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{less} = \lambda n\ .\ \lambda m\ .\ \operatorname{le}\ n\ (\operatorname{pred} m)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{eq} = \lambda n\ .\ \lambda m\ .\ \operatorname{and}\ (\operatorname{isZero}\ (\operatorname{minus}\ n\ m))\ &lt;br /&gt;
(\operatorname{isZero}\ (\operatorname{minus}\ m\ n))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Комбинатор неподвижной точки===&lt;br /&gt;
Попробуем выразить в лямбда-исчислении какую-нибудь функцию, использующую рекурсию. Напрмер, факториал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{fact} = \lambda x\ .\ \operatorname{if}\ (\operatorname{isZero}\ x)\ \bar 1\ (\operatorname{fact}\ (\operatorname{pred}\ x))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Мы столкнулись с проблемой. В определении функции &amp;lt;tex&amp;gt;\operatorname{fact}&amp;lt;/tex&amp;gt; используется функция &amp;lt;tex&amp;gt;\operatorname{fact}&amp;lt;/tex&amp;gt;. При формальной замене, получим бесконечную функцию. Можно попытаться решить эту проблему следующим образом&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{fact} = (\lambda f\ .\ \lambda x\ .\ \operatorname{if}\ (\operatorname{isZero}\ x)\ \bar 1\ (f\ (\operatorname{pred}\ x)))\ \operatorname{fact}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=''Неподвижной точкой'' лямбда-функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; назовём такую функцию &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, что&lt;br /&gt;
&amp;lt;tex&amp;gt;f\ x \to_\beta^* x&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;
&amp;lt;tex&amp;gt;\operatorname{fix} = \lambda f\ .\ (\lambda x\ .\ f\ (x\ x))\ (\lambda x\ .\ f\ (x\ x))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Заметим, что &amp;lt;tex&amp;gt;\operatorname{fix} \to_\beta^* \lambda f\ .\ f\ ((\lambda x\ .\ f\ (x\ x))\ (\lambda x\ .\ f\ (x\ x)))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Или, что то же самое, &lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda f\ .\ (\lambda x\ .\ f\ (x\ x))\ (\lambda x\ .\ f\ (x\ x)) \to_\beta^*&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda f\ .\ f\ ((\lambda x\ .\ f\ (x\ x))\ (\lambda x\ .\ f\ (x\ x)))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим функцию&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{fact'} = \lambda f\ .\ \lambda x\ .\ \operatorname{if}\ (\operatorname{isZero}\ x)\ \bar 1\ (\operatorname{mult}\ x\ (f\ (\operatorname{pred}\ x)))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как было показано выше, &amp;lt;tex&amp;gt;\operatorname{fix} f \to_\beta^* f\ (\operatorname{fix} f)&amp;lt;/tex&amp;gt;, то есть, &amp;lt;tex&amp;gt;\operatorname{fix}\ \operatorname{fact'} \to_\beta^* \operatorname{fact}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\operatorname{fact}&amp;lt;/tex&amp;gt; {{---}} искомая функция, считающая факториал.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{fact} = \operatorname{fix}\ \operatorname{fact'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это даст функцию, которая посчитает факториал числа. Но делать она это будет мееедленно-меееедленно. Для того, чтобы посчитать &amp;lt;tex&amp;gt;5!&amp;lt;/tex&amp;gt; потребовалось сделать 66066 &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукций.&lt;br /&gt;
&lt;br /&gt;
Наиболее известным комбинатором неподвижной точки является &amp;lt;tex&amp;gt;Y&amp;lt;/tex&amp;gt;-комбинатор, введенный известным американским ученым Хаскеллом Карри как&lt;br /&gt;
:&amp;lt;tex&amp;gt;Y\ = \ \lambda f.(\lambda x.f(x\ x))\ (\lambda x.f(x\ x))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Деление===&lt;br /&gt;
Воспользовавшись идеей о том, что можно делать рекурсивные функции, сделаем функцию, которая будет искать частное двух чисел.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{div'} = \lambda div\ .\ \lambda n\ .\ \lambda m\ .\ \operatorname{if}\ (\operatorname{less}\ n\ m)\ \bar 0\ (\operatorname{succ}\ (div\ (\operatorname{minus}\ n\ m)\ m))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{div} = \operatorname{fix}\ \operatorname{div'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И остатка от деления&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{mod'} = \lambda mod\ .\ \lambda n\ .\ \lambda m\ .\ \operatorname{if}\ (\operatorname{less}\ n\ m)\ n\ (mod\ (\operatorname{minus}\ n\ m)\ m)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{mod} = \operatorname{fix}\ \operatorname{mod'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Проверка на простоту===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{isPrimeHelp}&amp;lt;/tex&amp;gt; {{---}} принимает число, которое требуется проверить на простоту и то, на что его надо опытаться поделить, перебирая это от 2 до &amp;lt;tex&amp;gt;p-1&amp;lt;/tex&amp;gt;. Если на что-нибудь разделилось, то число {{---}} составное, иначе {{---}} простое.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{isPrimeHelp'} =&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\lambda f\ .\ \lambda p\ .\ \lambda i\ .\ \operatorname{if}\ (\operatorname{le}\ p\ i)\ \operatorname{true}\ (\operatorname{if}\ (\operatorname{isZero}\ (\operatorname{mod}\ p\ i))\ \operatorname{false}\ (f\ p\ (\operatorname{succ}\ i)))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{isPrimeHelp} = \operatorname{fix}\ \operatorname{isPrimeHelp'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{isPrime} = \lambda p\ .\ \operatorname{isPrimeHelp}\ p\ \bar 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующее простое число. &amp;lt;tex&amp;gt;\operatorname{nextPrime'}&amp;lt;/tex&amp;gt; {{---}} следующее, больше либо равное заданного, &amp;lt;tex&amp;gt;\operatorname{nextPrime}&amp;lt;/tex&amp;gt; {{---}} следующее, большее заданного.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{nextPrime''} = \lambda f\ .\ \lambda p\ .\ \operatorname{if}\ (\operatorname{isPrime}\ p)\ p\ (f\ (\operatorname{succ}\ p)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{nextPrime'} = \operatorname{fix}\ \operatorname{nextPrime'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{nextPrime} = \lambda p\ .\ \operatorname{nextPrime'}\ (\operatorname{succ}\ p)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{ithPrimeStep}&amp;lt;/tex&amp;gt; пропрыгает &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; простых чисел вперёд. &amp;lt;tex&amp;gt;\operatorname{ithPrime}&amp;lt;/tex&amp;gt; принимает число &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и пропрыгивает столько простых чисел вперёд, начиная с двойки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{ithPrimeStep'} = \lambda f\ .\ \lambda p\ .\ \lambda i\ .\ \operatorname{if}\ (\operatorname{isZero}\ i)\ p\ (f\  (\operatorname{nextPrime}\ p)\ (\operatorname{pred}\ i))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{ithPrimeStep} = \operatorname{fix}\ \operatorname{ithPrimeStep'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{ithPrime} = \lambda i\ .\ \operatorname{ithPrimeStep}\ \bar 2\ i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...и всего через 314007 &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt;-редукций вы узнаете, что третье простое число {{---}} семь!&lt;br /&gt;
&lt;br /&gt;
===Списки===&lt;br /&gt;
&lt;br /&gt;
Для работы со списками чисел нам понадобятся следующие функции:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\operatorname{empty}&amp;lt;/tex&amp;gt; {{---}} возвращает пустой список&lt;br /&gt;
* &amp;lt;tex&amp;gt;\operatorname{cons}&amp;lt;/tex&amp;gt; {{---}} принимает первый элемент и оставшийся список, склеивает их&lt;br /&gt;
* &amp;lt;tex&amp;gt;\operatorname{head}&amp;lt;/tex&amp;gt; {{---}} вернуть голову списка&lt;br /&gt;
* &amp;lt;tex&amp;gt;\operatorname{tail}&amp;lt;/tex&amp;gt; {{---}} вернуть хвост списка&lt;br /&gt;
&lt;br /&gt;
Список будем хранить в следующем виде: &amp;lt;tex&amp;gt;\langle len, p_1^{a_1}p_2^{a_2}\ldots p_{len}^{a_{len}} \rangle&amp;lt;/tex&amp;gt;. При этом, голова списка будет храниться как показатель степени при &amp;lt;tex&amp;gt;p_{len}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{empty} = \operatorname{pair}\ \operatorname{zero}\ \bar 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{cons} = \lambda h\ .\ \lambda t\ .\ \operatorname{pair}\ (\operatorname{succ}\ (\operatorname{fst}\ t))\ (\operatorname{mult}\ (\operatorname{snd}\ t)\ (\operatorname{power}\ (\operatorname{ithPrime}\ (\operatorname{fst}\ t))\ h))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{head} = \lambda list\ .\ \operatorname{getExponent}\ (\operatorname{snd}\ list)\ (\operatorname{ithPrime}\ (\operatorname{pred}\ (\operatorname{fst}\ list)))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{tail} = \lambda list\ .\ \operatorname{pair}\ (\operatorname{pred}\ (\operatorname{fst}\ list))&lt;br /&gt;
 (\operatorname{eliminateMultiplier}\ (\operatorname{snd}\ list)\ (\operatorname{ithPrime}\ (\operatorname{pred}\ (\operatorname{fst}\ list))))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{eliminateMultiplier'} =&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \lambda f\ .\ \lambda n\ .\ \lambda m\ .\ \operatorname{if}\ (\operatorname{isZero}\ (\operatorname{mod}\ n\ m))\ (f\ (\operatorname{div}\ n\ m)\ m)\ n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{eliminateMultiplier} = \operatorname{fix}\ \operatorname{eliminateMultiplier'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{getExponent'} =&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \lambda f\ .\ \lambda n\ .\ \lambda m\ .\ \operatorname{if}\ (\operatorname{isZero}\ (\operatorname{mod}\ n\ m))\ (\operatorname{succ}\ (f\ (\operatorname{div}\ n\ m)\ m))\ \bar 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\operatorname{getExponent} = \operatorname{fix}\ \operatorname{getExponent'}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Выводы==&lt;br /&gt;
&lt;br /&gt;
На основе этого всего уже можно реализовать эмулятор машины тьюринга: с помощью пар, списков чисел можно хранить состояния. С помощью рекурсии можно обрабатывать переходы. Входная строка будет даваться, например, закодированной аналогично списку: пара из длины и числа, характеризующего список степенями простых. Я бы продолжил это писать, но уже на операции &amp;lt;tex&amp;gt;\operatorname{head} [1, 2]&amp;lt;/tex&amp;gt; я не дождался окончания выполнения. Скорость лямбда-исчисления как вычислителя печальна.&lt;br /&gt;
&lt;br /&gt;
==Примеры (слабонервным не смотреть)==&lt;br /&gt;
&lt;br /&gt;
====fact====&lt;br /&gt;
&amp;lt;tex&amp;gt;(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda x.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda s.\lambda z.s z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.\lambda s.n (m s))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (x)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (f ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (x)))))&amp;lt;/tex&amp;gt;&lt;br /&gt;
====head====&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda list.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda mod.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.\lambda m.(\lambda n.n(\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (m)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) n (mod ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) m)) n m)) ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (f ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda div.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (m)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) (\lambda s.\lambda z.z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (div ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) m))) n m) m)) (\lambda s.\lambda z.z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (list))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda i.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda p.\lambda i.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (i))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; p (f ((\lambda p.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda p.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda p.\lambda i.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (p)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; i) (\lambda a.\lambda b.a)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda mod.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (m)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) n (mod ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) m)) p i)) (\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (f p ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (i)))))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; p (\lambda s.\lambda z.s (s z)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; p (f ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p))))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (i))))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda s.\lambda z.s (s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; i) ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (list))))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====tail====&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda list.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (list)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda mod.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (m)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) n (mod ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) m)) n m)) (f ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda div.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (m)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) (\lambda s.\lambda z.z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (div ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) m))) n m) m) n) ((\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (list))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda i.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda p.\lambda i.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (i))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; p (f ((\lambda p.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda p.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.(\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda f.\lambda p.\lambda i.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (p)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; i) (\lambda a.\lambda b.a)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda f.(\lambda x.f (x x))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda x.f (x x)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda mod.\lambda n.\lambda m.(\lambda p.\lambda t.\lambda e.p t e)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.(\lambda n.\lambda m.(\lambda n.n (\lambda c.\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m)) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (m)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) n (mod ((\lambda n.\lambda m.m (\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) n) (n)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; m) m)) p i)) (\lambda a.\lambda b.b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (f p ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (i)))))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; p (\lambda s.\lambda z.s (s z)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; p (f ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p))))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.s (n s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) (i))))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (\lambda s.\lambda z.s (s z))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; i) ((\lambda n.\lambda s.\lambda z.(\lambda p.p (\lambda a.\lambda b.b))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (n (\lambda p.(\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (s ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (p)))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; ((\lambda a.\lambda b.\lambda t.t a b)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (z)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; z))) ((\lambda p.p (\lambda a.\lambda b.a))&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; (list)))))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[Неразрешимость задачи вывода типов в языке с зависимыми типами]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Lectures on the Curry Howard - Isomorphism&lt;br /&gt;
*[https://github.com/shd/tt2014 Д. Штукенберг. Лекции]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Lambda-calculus Английская Википедия]&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9B%D1%8F%D0%BC%D0%B1%D0%B4%D0%B0-%D0%B8%D1%81%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5 Русская Википедия]&lt;br /&gt;
*[http://worrydream.com/AlligatorEggs Игра про крокодилов]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Теория вычислимости]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63250</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63250"/>
				<updated>2017-12-31T05:50:38Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Анализ полученного алгоритмом паросочетания */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, так как количество итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда и некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) незамужняя. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; сделал предложения всем женщинам, так как он остался не женат. Получаем противоречие. Таким образом, все мужчины заняты.&lt;br /&gt;
&lt;br /&gt;
Аналогичные рассуждения применяем для женщин. Пусть какая-то женщина незамужняя. Значит, есть мужчина, который остался не женат. Но мы доказали, что по завершении алгоритма все мужчины заняты. Снова пришли к противоречию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. То есть для &amp;lt;tex&amp;gt;c&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются наименее привлекательными с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, то это будет означать, что она на самом деле осталась без пары.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63236</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63236"/>
				<updated>2017-12-30T13:57:05Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Обобщения задачи */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, так как количество итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда и некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) незамужняя. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; сделал предложения всем женщинам, так как он остался не женат. Получаем противоречие. Таким образом, все мужчины заняты.&lt;br /&gt;
&lt;br /&gt;
Аналогичные рассуждения применяем для женщин. Пусть какая-то женщина незамужняя. Значит, есть мужчина, который остался не женат. Но мы доказали, что по завершении алгоритма все мужчины заняты. Снова пришли к противоречию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются наименее привлекательными с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, то это будет означать, что она на самом деле осталась без пары.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63235</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63235"/>
				<updated>2017-12-30T13:54:57Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, так как количество итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда и некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) незамужняя. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; сделал предложения всем женщинам, так как он остался не женат. Получаем противоречие. Таким образом, все мужчины заняты.&lt;br /&gt;
&lt;br /&gt;
Аналогичные рассуждения применяем для женщин. Пусть какая-то женщина незамужняя. Значит, есть мужчина, который остался не женат. Но мы доказали, что по завершении алгоритма все мужчины заняты. Снова пришли к противоречию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63054</id>
		<title>Задача о динамической связности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63054"/>
				<updated>2017-12-26T21:26:36Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Реализация на C++ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Имеется [[Основные_определения:_граф,_ребро,_вершина,_степень,_петля,_путь,_цикл#Неориентированные_графы|неориентированный граф]] из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, изначально не содержащий рёбер. Требуется обработать &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; запросов трёх типов:&lt;br /&gt;
* добавить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* удалить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* проверить, лежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&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;
Время работы такого решения: &amp;lt;tex&amp;gt;O(m \cdot \alpha (n))&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\alpha&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;k&amp;lt;/tex&amp;gt; рёбер, &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е соединяет вершины &amp;lt;tex&amp;gt;v_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_i&amp;lt;/tex&amp;gt;, было добавлено запросом &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; и удалено запросом &amp;lt;tex&amp;gt;R_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим на массиве запросов [[Дерево отрезков. Построение|дерево отрезков]], в каждой его вершине будем хранить список пар. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е рёбро графа нужно добавить на отрезок &amp;lt;tex&amp;gt;[L_i,R_i]&amp;lt;/tex&amp;gt;. Это делается аналогично тому, как в дереве отрезков происходит добавление на отрезке (процесс описан в статье &amp;quot;[[Несогласованные поддеревья. Реализация массового обновления]]&amp;quot;), но без &amp;lt;tex&amp;gt;push&amp;lt;/tex&amp;gt;: нужно спуститься по дереву от корня и записать пару &amp;lt;tex&amp;gt;u_i,v_i&amp;lt;/tex&amp;gt; в вершины дерева отрезков.&lt;br /&gt;
&lt;br /&gt;
Теперь чтобы узнать, какие рёбра существуют во время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го запроса, достаточно посмотреть на путь от корня дерева отрезков до листа, который соответствует этому запросу {{---}} рёбра, записанные в вершинах этого пути, существуют во время выполнения запроса.&lt;br /&gt;
&lt;br /&gt;
=== Ответы на запросы ===&lt;br /&gt;
Обойдём дерево отрезков в глубину, начиная с корня. Будем поддерживать граф, состоящий из рёбер, которые содержатся на пути от текущей вершины дерева отрезков до корня. При входе в вершину добавим в граф рёбра, записанные в этой вершине. При выходе из вершины нужно откатить граф к состоянию, которое было при входе. Когда мы добираемся до листа, в граф уже добавлены все рёбра, которые существуют во время выполнения соответствующего запроса, и только они. Поэтому если этот лист соответствует запросу третьего типа, его следует выполнить и сохранить ответ.&lt;br /&gt;
&lt;br /&gt;
Для поддержания такого графа и ответа на запросы будем использовать [[СНМ (реализация с помощью леса корневых деревьев)|систему непересекающихся множеств]]. При добавлении рёбер в граф объединим соответствующие множества в СНМ. Откатывание состояния СНМ описано ниже.&lt;br /&gt;
&lt;br /&gt;
=== СНМ с откатами ===&lt;br /&gt;
Для того, чтобы иметь возможность откатывать состояние СНМ, нужно при каждом изменении любого значения в СНМ записывать в специальный массив, что именно изменилось и какое было предыдущее значение. Это можно реализовать как массив пар (указатель, значение).&lt;br /&gt;
&lt;br /&gt;
Чтобы откатить состояние СНМ, пройдём по этому массиву в обратном порядке и присвоим старые значения обратно. Для лучшего понимания ознакомьтесь с приведённой ниже реализацией.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что эвристику сжатия путей в этом случае применять не следует. Эта эвристика улучшает асимптотическое время работы, но это время работы не истинное, а амортизированное. Из-за наличия откатов к предыдущим состояниям эта эвристика не даст выигрыша. СНМ с ранговой эвристикой же работает за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; на запрос истинно.&lt;br /&gt;
&lt;br /&gt;
Запоминание изменений и откаты не влияют на время работы, если оно истинное, а не амортизированное. Действительно: пусть в СНМ произошло &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; изменений. Каждое из них будет один раз занесено в массив и один раз отменено. Значит, запись в массив и откаты работают за &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt;. Но и сами изменения заняли &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt; времени, значит, откаты не увеличили асимптотическое время работы.&lt;br /&gt;
&lt;br /&gt;
Вместо описанного способа откатывания состояния СНМ можно использовать [[Персистентные структуры данных|персистентный]] СНМ, но этот вариант сложнее и имеет меньшую эффективность. &amp;lt;!-- Я не уверен, бывает ли персистентный СНМ, работающий за log. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Время работы ==&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)|Система непересекающихся множеств]]&lt;br /&gt;
* [[Дерево отрезков. Построение|Дерево отрезков]]&lt;br /&gt;
* [[Задача о динамической связности оффлайн]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Связность в графах]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63053</id>
		<title>Задача о динамической связности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63053"/>
				<updated>2017-12-26T21:20:09Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Имеется [[Основные_определения:_граф,_ребро,_вершина,_степень,_петля,_путь,_цикл#Неориентированные_графы|неориентированный граф]] из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, изначально не содержащий рёбер. Требуется обработать &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; запросов трёх типов:&lt;br /&gt;
* добавить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* удалить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* проверить, лежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&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;
Время работы такого решения: &amp;lt;tex&amp;gt;O(m \cdot \alpha (n))&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\alpha&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;k&amp;lt;/tex&amp;gt; рёбер, &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е соединяет вершины &amp;lt;tex&amp;gt;v_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_i&amp;lt;/tex&amp;gt;, было добавлено запросом &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; и удалено запросом &amp;lt;tex&amp;gt;R_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим на массиве запросов [[Дерево отрезков. Построение|дерево отрезков]], в каждой его вершине будем хранить список пар. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е рёбро графа нужно добавить на отрезок &amp;lt;tex&amp;gt;[L_i,R_i]&amp;lt;/tex&amp;gt;. Это делается аналогично тому, как в дереве отрезков происходит добавление на отрезке (процесс описан в статье &amp;quot;[[Несогласованные поддеревья. Реализация массового обновления]]&amp;quot;), но без &amp;lt;tex&amp;gt;push&amp;lt;/tex&amp;gt;: нужно спуститься по дереву от корня и записать пару &amp;lt;tex&amp;gt;u_i,v_i&amp;lt;/tex&amp;gt; в вершины дерева отрезков.&lt;br /&gt;
&lt;br /&gt;
Теперь чтобы узнать, какие рёбра существуют во время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го запроса, достаточно посмотреть на путь от корня дерева отрезков до листа, который соответствует этому запросу {{---}} рёбра, записанные в вершинах этого пути, существуют во время выполнения запроса.&lt;br /&gt;
&lt;br /&gt;
=== Ответы на запросы ===&lt;br /&gt;
Обойдём дерево отрезков в глубину, начиная с корня. Будем поддерживать граф, состоящий из рёбер, которые содержатся на пути от текущей вершины дерева отрезков до корня. При входе в вершину добавим в граф рёбра, записанные в этой вершине. При выходе из вершины нужно откатить граф к состоянию, которое было при входе. Когда мы добираемся до листа, в граф уже добавлены все рёбра, которые существуют во время выполнения соответствующего запроса, и только они. Поэтому если этот лист соответствует запросу третьего типа, его следует выполнить и сохранить ответ.&lt;br /&gt;
&lt;br /&gt;
Для поддержания такого графа и ответа на запросы будем использовать [[СНМ (реализация с помощью леса корневых деревьев)|систему непересекающихся множеств]]. При добавлении рёбер в граф объединим соответствующие множества в СНМ. Откатывание состояния СНМ описано ниже.&lt;br /&gt;
&lt;br /&gt;
=== СНМ с откатами ===&lt;br /&gt;
Для того, чтобы иметь возможность откатывать состояние СНМ, нужно при каждом изменении любого значения в СНМ записывать в специальный массив, что именно изменилось и какое было предыдущее значение. Это можно реализовать как массив пар (указатель, значение).&lt;br /&gt;
&lt;br /&gt;
Чтобы откатить состояние СНМ, пройдём по этому массиву в обратном порядке и присвоим старые значения обратно. Для лучшего понимания ознакомьтесь с приведённой ниже реализацией.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что эвристику сжатия путей в этом случае применять не следует. Эта эвристика улучшает асимптотическое время работы, но это время работы не истинное, а амортизированное. Из-за наличия откатов к предыдущим состояниям эта эвристика не даст выигрыша. СНМ с ранговой эвристикой же работает за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; на запрос истинно.&lt;br /&gt;
&lt;br /&gt;
Запоминание изменений и откаты не влияют на время работы, если оно истинное, а не амортизированное. Действительно: пусть в СНМ произошло &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; изменений. Каждое из них будет один раз занесено в массив и один раз отменено. Значит, запись в массив и откаты работают за &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt;. Но и сами изменения заняли &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt; времени, значит, откаты не увеличили асимптотическое время работы.&lt;br /&gt;
&lt;br /&gt;
Вместо описанного способа откатывания состояния СНМ можно использовать [[Персистентные структуры данных|персистентный]] СНМ, но этот вариант сложнее и имеет меньшую эффективность. &amp;lt;!-- Я не уверен, бывает ли персистентный СНМ, работающий за log. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Время работы ==&lt;br /&gt;
&lt;br /&gt;
== Реализация на C++ ==&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;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63052</id>
		<title>Задача о динамической связности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63052"/>
				<updated>2017-12-26T20:48:29Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Замечания */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Имеется [[Основные_определения:_граф,_ребро,_вершина,_степень,_петля,_путь,_цикл#Неориентированные_графы|неориентированный граф]] из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, изначально не содержащий рёбер. Требуется обработать &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; запросов трёх типов:&lt;br /&gt;
* добавить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* удалить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* проверить, лежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в одной компоненте связности.&lt;br /&gt;
В графе могут быть кратные рёбра и петли.&lt;br /&gt;
}}&lt;br /&gt;
погодь&lt;br /&gt;
&lt;br /&gt;
== Решение упрощённой задачи ==&lt;br /&gt;
Если нет удалений рёбер, задачу можно решить при помощи [[СНМ (реализация с помощью леса корневых деревьев)|системы непересекающихся множеств]]. Каждая компонента связности {{---}} одно множество в СНМ, и при добавлении рёбер они объединяются.&lt;br /&gt;
&lt;br /&gt;
Время работы такого решения: &amp;lt;tex&amp;gt;O(m \cdot \alpha (n))&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\alpha&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;k&amp;lt;/tex&amp;gt; рёбер, &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е соединяет вершины &amp;lt;tex&amp;gt;v_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_i&amp;lt;/tex&amp;gt;, было добавлено запросом &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; и удалено запросом &amp;lt;tex&amp;gt;R_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим на массиве запросов [[Дерево отрезков. Построение|дерево отрезков]], в каждой его вершине будем хранить список пар. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е рёбро графа нужно добавить на отрезок &amp;lt;tex&amp;gt;[L_i,R_i]&amp;lt;/tex&amp;gt;. Это делается аналогично тому, как в дереве отрезков происходит добавление на отрезке (процесс описан в статье &amp;quot;[[Несогласованные поддеревья. Реализация массового обновления]]&amp;quot;), но без &amp;lt;tex&amp;gt;push&amp;lt;/tex&amp;gt;: нужно спуститься по дереву от корня и записать пару &amp;lt;tex&amp;gt;u_i,v_i&amp;lt;/tex&amp;gt; в вершины дерева отрезков.&lt;br /&gt;
&lt;br /&gt;
Теперь чтобы узнать, какие рёбра существуют во время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го запроса, достаточно посмотреть на путь от корня дерева отрезков до листа, который соответствует этому запросу {{---}} рёбра, записанные в вершинах этого пути, существуют во время выполнения запроса.&lt;br /&gt;
&lt;br /&gt;
=== Ответы на запросы ===&lt;br /&gt;
Обойдём дерево отрезков в глубину, начиная с корня. Будем поддерживать граф, состоящий из рёбер, которые содержатся на пути от текущей вершины дерева отрезков до корня. При входе в вершину добавим в граф рёбра, записанные в этой вершине. При выходе из вершины нужно откатить граф к состоянию, которое было при входе. Когда мы добираемся до листа, в граф уже добавлены все рёбра, которые существуют во время выполнения соответствующего запроса, и только они. Поэтому если этот лист соответствует запросу третьего типа, его следует выполнить и сохранить ответ.&lt;br /&gt;
&lt;br /&gt;
Для поддержания такого графа и ответа на запросы будем использовать [[СНМ (реализация с помощью леса корневых деревьев)|систему непересекающихся множеств]]. При добавлении рёбер в граф объединим соответствующие множества в СНМ. Откатывание состояния СНМ описано ниже.&lt;br /&gt;
&lt;br /&gt;
=== СНМ с откатами ===&lt;br /&gt;
Для того, чтобы иметь возможность откатывать состояние СНМ, нужно при каждом изменении любого значения в СНМ записывать в специальный массив, что именно изменилось и какое было предыдущее значение. Это можно реализовать как массив пар (указатель, значение).&lt;br /&gt;
&lt;br /&gt;
Чтобы откатить состояние СНМ, пройдём по этому массиву в обратном порядке и присвоим старые значения обратно. Для лучшего понимания ознакомьтесь с приведённой ниже реализацией.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что эвристику сжатия путей в этом случае применять не следует. Эта эвристика улучшает асимптотическое время работы, но это время работы не истинное, а амортизированное. Из-за наличия откатов к предыдущим состояниям эта эвристика не даст выигрыша. СНМ с ранговой эвристикой же работает за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; на запрос истинно.&lt;br /&gt;
&lt;br /&gt;
Запоминание изменений и откаты не влияют на время работы, если оно истинное, а не амортизированное. Действительно: пусть в СНМ произошло &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; изменений. Каждое из них будет один раз занесено в массив и один раз отменено. Значит, запись в массив и откаты работают за &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt;. Но и сами изменения заняли &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt; времени, значит, откаты не увеличили асимптотическое время работы.&lt;br /&gt;
&lt;br /&gt;
Вместо описанного способа откатывания состояния СНМ можно использовать [[Персистентные структуры данных|персистентный]] СНМ, но этот вариант сложнее и имеет меньшую эффективность. &amp;lt;!-- Я не уверен, бывает ли персистентный СНМ, работающий за log. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Время работы ==&lt;br /&gt;
Каждое из &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; рёбер записывается в &amp;lt;tex&amp;gt;O(\log m)&amp;lt;/tex&amp;gt; вершин дерева отрезков. Поэтому операций &amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt; в СНМ будет &amp;lt;tex&amp;gt;O(m \log m)&amp;lt;/tex&amp;gt;. Каждая выполняется за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; (СНМ с ранговой эвристикой). Откаты не влияют на время работы.&lt;br /&gt;
&lt;br /&gt;
Можно считать, что &amp;lt;tex&amp;gt;n = O(\log m)&amp;lt;/tex&amp;gt;, так как в запросах используется не более &amp;lt;tex&amp;gt;2m&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Время работы: &amp;lt;tex&amp;gt;O(m \log m \log n) = O(m \log^2 m)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
== Реализация на C++ ==&lt;br /&gt;
 '''#include''' &amp;lt;bits/stdc++.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''using''' '''namespace''' std;&lt;br /&gt;
 '''typedef''' pair &amp;lt; '''int''' , '''int''' &amp;gt; ipair;&lt;br /&gt;
 '''const''' '''int''' N = 100321;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// СНМ&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''int''' dsuP[N], dsuR[N];&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// В этот массив записываются все изменения СНМ, чтобы их можно откатить&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При изменении какого-то значения в СНМ в hist записывается пара &amp;lt; указатель, старое значение &amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 vector &amp;lt; pair &amp;lt; '''int'''*, '''int''' &amp;gt; &amp;gt; hist;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для элемента из СНМ возвращает корень дерева, в котором он находится&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''int''' dsuRoot('''int''' v)&lt;br /&gt;
 {&lt;br /&gt;
     '''while''' (dsuP[v] != -1)&lt;br /&gt;
         v = dsuP[v];&lt;br /&gt;
     '''return''' v;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Объединяет два множества. Используется ранговая эвристика.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При любом изменении содержимого массивов dsuP и dsuR&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// в hist записывается адрес и старое значение&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''void''' dsuMerge('''int''' a, '''int''' b)&lt;br /&gt;
 {&lt;br /&gt;
     a = dsuRoot(a);&lt;br /&gt;
     b = dsuRoot(b);&lt;br /&gt;
     '''if''' (a == b)&lt;br /&gt;
         '''return''';&lt;br /&gt;
     '''if''' (dsuR[a] &amp;gt; dsuR[b])&lt;br /&gt;
     {&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuP[b], dsuP[b]);&lt;br /&gt;
         dsuP[b] = a;&lt;br /&gt;
     } '''else''' '''if''' (dsuR[a] &amp;lt; dsuR[b])&lt;br /&gt;
     {&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuP[a], dsuP[a]);&lt;br /&gt;
         dsuP[a] = b;&lt;br /&gt;
     } '''else'''&lt;br /&gt;
     {&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuP[a], dsuP[a]);&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuR[b], dsuR[b]);&lt;br /&gt;
         dsuP[a] = b;&lt;br /&gt;
         ++dsuR[b];&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 '''struct''' Query&lt;br /&gt;
 {&lt;br /&gt;
     '''int''' t, u, v;&lt;br /&gt;
     bool answer;&lt;br /&gt;
 };&lt;br /&gt;
 '''int''' n, m;&lt;br /&gt;
 Query q[N];&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Дерево отрезков, в каждой вершине которого хранится список рёбер&amp;lt;/font&amp;gt;&lt;br /&gt;
 vector &amp;lt; ipair &amp;gt; t[N*4];&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Эта функция добавляет ребро на отрезок&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// [l r] - отрезок, на который добавляется ребро&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// uv - ребро, c - текущая вершина дерева отрезков,&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// [cl cr] - отрезок текущей вершины дерева отрезков&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''void''' addEdge('''int''' l, '''int''' r, ipair uv, '''int''' c, '''int''' cl, '''int''' cr)&lt;br /&gt;
 {&lt;br /&gt;
     '''if''' (l &amp;gt; cr || r &amp;lt; cl)&lt;br /&gt;
         '''return''';&lt;br /&gt;
     '''if''' (l &amp;lt;= cl &amp;amp;&amp;amp; cr &amp;lt;= r)&lt;br /&gt;
     {&lt;br /&gt;
         t[c].push_back(uv);&lt;br /&gt;
         '''return''';&lt;br /&gt;
     }&lt;br /&gt;
     '''int''' mid = (cl + cr) / 2;&lt;br /&gt;
     addEdge(l, r, uv, c*2+1, cl, mid);&lt;br /&gt;
     addEdge(l, r, uv, c*2+2, mid+1, cr);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Обход дерева отрезков в глубину&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''void''' go('''int''' c, '''int''' cl, '''int''' cr)&lt;br /&gt;
 {&lt;br /&gt;
     '''int''' startSize = hist.size();&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем рёбра при входе в вершину&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' (ipair uv : t[c])&lt;br /&gt;
         dsuMerge(uv.first, uv.second);&lt;br /&gt;
 &lt;br /&gt;
     '''if''' (cl == cr)&lt;br /&gt;
     {&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Если эта вершина - лист, то отвечаем на запрос&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' (q[cl].t == 3)&lt;br /&gt;
             q[cl].answer = (dsuRoot(q[cl].u) == dsuRoot(q[cl].v));&lt;br /&gt;
     } '''else''' {&lt;br /&gt;
         '''int''' mid = (cl + cr) / 2;&lt;br /&gt;
         go(c*2+1, cl, mid);&lt;br /&gt;
         go(c*2+2, mid+1, cr);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Откатываем изменения СНМ&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' (('''int''')hist.size() &amp;gt; startSize)&lt;br /&gt;
     {&lt;br /&gt;
         *hist.back().first = hist.back().second;&lt;br /&gt;
         hist.pop_back();&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 '''int''' main()&lt;br /&gt;
 {&lt;br /&gt;
     ios::sync_with_stdio('''false''');&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Формат входных данных:&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// n и m, затем в m строках запросы: по три числа t, u, v&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// t - тип (1 - добавить ребро, 2 - удалить, 3 - принадлежат ли одной компоненте)&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Нумерация вершин с нуля&amp;lt;/font&amp;gt;&lt;br /&gt;
     cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;&lt;br /&gt;
     '''for''' ('''int''' i = 0; i &amp;lt; n; ++i) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализация СНМ&amp;lt;/font&amp;gt;&lt;br /&gt;
         dsuP[i] = -1;&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// В этом массиве для каждого ещё не удалённого ребра хранится&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// на каком запросе оно было создано&amp;lt;/font&amp;gt;&lt;br /&gt;
     set &amp;lt; pair &amp;lt; ipair, '''int''' &amp;gt; &amp;gt; edges;&lt;br /&gt;
     '''for''' ('''int''' i = 0; i &amp;lt; m; ++i)&lt;br /&gt;
     {&lt;br /&gt;
         cin &amp;gt;&amp;gt; q[i].t &amp;gt;&amp;gt; q[i].u &amp;gt;&amp;gt; q[i].v;&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Поскольку рёбра неориентированные, u v должно означать то же самое, что и v u&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' (q[i].u &amp;gt; q[i].v) swap(q[i].u, q[i].v);&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При добавлении ребра кладём его в set&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' (q[i].t == 1)&lt;br /&gt;
             edges.emplace(ipair(q[i].u, q[i].v), i);&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При удалении ребра берём из set время его добавления - так мы узнаём отрезок заросов,&amp;lt;/font&amp;gt;&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// на котором оно существует. Если есть несколько одинаковых рёбер, можно брать любое.&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''else''' '''if''' (q[i].t == 2)&lt;br /&gt;
         {&lt;br /&gt;
             '''auto''' iter = edges.lower_bound(make_pair(ipair(q[i].u, q[i].v), 0));&lt;br /&gt;
             addEdge(iter-&amp;gt;second, i, iter-&amp;gt;first, 0, 0, m - 1);&lt;br /&gt;
             edges.erase(iter);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Обрабатываем рёбра, которые не были удалены&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' ('''auto''' e : edges)&lt;br /&gt;
         addEdge(e.second, m - 1, e.first, 0, 0, m - 1);&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Запускаем dfs по дереву отрезков&amp;lt;/font&amp;gt;&lt;br /&gt;
     go(0, 0, m - 1);&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выводим ответ.&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При обходе дерева отрезков запросы обрабатываются в том же порядке, в котором они даны,&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// поэтому ответ можно выводить прямо в go без заполнения answer&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' ('''int''' i = 0; i &amp;lt; m; ++i)&lt;br /&gt;
         '''if''' (q[i].t == 3)&lt;br /&gt;
         {&lt;br /&gt;
             '''if''' (q[i].answer)&lt;br /&gt;
                 cout &amp;lt;&amp;lt; &amp;quot;YES\n&amp;quot;;&lt;br /&gt;
             '''else'''&lt;br /&gt;
                 cout &amp;lt;&amp;lt; &amp;quot;NO\n&amp;quot;;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
     '''return''' 0;&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;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63048</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63048"/>
				<updated>2017-12-26T15:59:36Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, так как количество итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; сделал предложения всем женщинам, так как он остался не женат. Получаем противоречие. Таким образом, все мужчины заняты.&lt;br /&gt;
&lt;br /&gt;
Аналогичные рассуждения применяем для женщин. Пусть какая-то женщина незамужняя. Значит, есть мужчина, который остался не женат. Но мы доказали, что по завершении алгоритма все мужчины заняты. Снова пришли к противоречию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63047</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63047"/>
				<updated>2017-12-26T15:01:34Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, так как количество итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; сделал предложения всем женщинам, так как он остался не женат. Получаем противоречие. Таким образом, все мужчины заняты.&lt;br /&gt;
&lt;br /&gt;
Аналогичные рассуждения применяем для женщин. Пусть какая-то женщина не замужем. Значит, есть мужчина, который остался не женат. Но мы доказали, что по завершении алгоритма все мужчины заняты. Снова пришли к противоречию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63046</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63046"/>
				<updated>2017-12-26T15:00:18Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Описание в псевдокоде */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, так как количество итераций цикла &amp;lt;tex&amp;gt;\mathrm {while}&amp;lt;/tex&amp;gt; не превосходит &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&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;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63045</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63045"/>
				<updated>2017-12-26T14:51:18Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Асимптотика алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&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;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара&lt;br /&gt;
	&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63021</id>
		<title>Задача о динамической связности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=63021"/>
				<updated>2017-12-25T21:01:35Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: new article&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Имеется [[Основные_определения:_граф,_ребро,_вершина,_степень,_петля,_путь,_цикл#Неориентированные_графы|неориентированный граф]] из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, изначально не содержащий рёбер. Требуется обработать &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; запросов трёх типов:&lt;br /&gt;
* добавить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* удалить ребро между вершинами &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* проверить, лежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в одной компоненте связности.&lt;br /&gt;
В графе могут быть кратные рёбра и петли.&lt;br /&gt;
}}&lt;br /&gt;
погодь&lt;br /&gt;
&lt;br /&gt;
== Решение упрощённой задачи ==&lt;br /&gt;
Если нет удалений рёбер, задачу можно решить при помощи [[СНМ (реализация с помощью леса корневых деревьев)|системы непересекающихся множеств]]. Каждая компонента связности {{---}} одно множество в СНМ, и при добавлении рёбер они объединяются.&lt;br /&gt;
&lt;br /&gt;
Время работы такого решения: &amp;lt;tex&amp;gt;O(m \cdot \alpha (n))&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\alpha&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;k&amp;lt;/tex&amp;gt; рёбер, &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е соединяет вершины &amp;lt;tex&amp;gt;v_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_i&amp;lt;/tex&amp;gt;, было добавлено запросом &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; и удалено запросом &amp;lt;tex&amp;gt;R_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим на массиве запросов [[Дерево отрезков. Построение|дерево отрезков]], в каждой его вершине будем хранить список пар. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е рёбро графа нужно добавить на отрезок &amp;lt;tex&amp;gt;[L_i,R_i]&amp;lt;/tex&amp;gt;. Это делается аналогично тому, как в дереве отрезков происходит добавление на отрезке (процесс описан в статье &amp;quot;[[Несогласованные поддеревья. Реализация массового обновления]]&amp;quot;), но без &amp;lt;tex&amp;gt;push&amp;lt;/tex&amp;gt;: нужно спуститься по дереву от корня и записать пару &amp;lt;tex&amp;gt;u_i,v_i&amp;lt;/tex&amp;gt; в вершины дерева отрезков.&lt;br /&gt;
&lt;br /&gt;
Теперь чтобы узнать, какие рёбра существуют во время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го запроса, достаточно посмотреть на путь от корня дерева отрезков до листа, который соответствует этому запросу {{---}} рёбра, записанные в вершинах этого пути, существуют во время выполнения запроса.&lt;br /&gt;
&lt;br /&gt;
=== Ответы на запросы ===&lt;br /&gt;
Обойдём дерево отрезков в глубину, начиная с корня. Будем поддерживать граф, состоящий из рёбер, которые содержатся на пути от текущей вершины дерева отрезков до корня. При входе в вершину добавим в граф рёбра, записанные в этой вершине. При выходе из вершины нужно откатить граф к состоянию, которое было при входе. Когда мы добираемся до листа, в граф уже добавлены все рёбра, которые существуют во время выполнения соответствующего запроса, и только они. Поэтому если этот лист соответствует запросу третьего типа, его следует выполнить и сохранить ответ.&lt;br /&gt;
&lt;br /&gt;
Для поддержания такого графа и ответа на запросы будем использовать [[СНМ (реализация с помощью леса корневых деревьев)|систему непересекающихся множеств]]. При добавлении рёбер в граф объединим соответствующие множества в СНМ. Откатывание состояния СНМ описано ниже.&lt;br /&gt;
&lt;br /&gt;
=== СНМ с откатами ===&lt;br /&gt;
Для того, чтобы иметь возможность откатывать состояние СНМ, нужно при каждом изменении любого значения в СНМ записывать в специальный массив, что именно изменилось и какое было предыдущее значение. Это можно реализовать как массив пар (указатель, значение).&lt;br /&gt;
&lt;br /&gt;
Чтобы откатить состояние СНМ, пройдём по этому массиву в обратном порядке и присвоим старые значения обратно. Для лучшего понимания ознакомьтесь с приведённой ниже реализацией.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что эвристику сжатия путей в этом случае применять не следует. Эта эвристика улучшает асимптотическое время работы, но это время работы не истинное, а амортизированное. Из-за наличия откатов к предыдущим состояниям эта эвристика не даст выигрыша. СНМ с ранговой эвристикой же работает за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; на запрос истинно.&lt;br /&gt;
&lt;br /&gt;
Запоминание изменений и откаты не влияют на время работы, если оно истинное, а не амортизированное. Действительно: пусть в СНМ произошло &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; изменений. Каждое из них будет один раз занесено в массив и один раз отменено. Значит, запись в массив и откаты работают за &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt;. Но и сами изменения заняли &amp;lt;tex&amp;gt;\Theta(r)&amp;lt;/tex&amp;gt; времени, значит, откаты не увеличили асимптотическое время работы.&lt;br /&gt;
&lt;br /&gt;
Вместо описанного способа откатывания состояния СНМ можно использовать [[Персистентные структуры данных|персистентный]] СНМ, но этот вариант сложнее и имеет меньшую эффективность. &amp;lt;!-- Я не уверен, бывает ли персистентный СНМ, работающий за log. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Время работы ==&lt;br /&gt;
Каждое из &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; рёбер записывается в &amp;lt;tex&amp;gt;O(\log m)&amp;lt;/tex&amp;gt; вершин дерева отрезков. Поэтому операций &amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt; в СНМ будет &amp;lt;tex&amp;gt;O(m \log m)&amp;lt;/tex&amp;gt;. Каждая выполняется за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; (СНМ с ранговой эвристикой). Откаты не влияют на время работы.&lt;br /&gt;
&lt;br /&gt;
Можно считать, что &amp;lt;tex&amp;gt;n = O(\log m)&amp;lt;/tex&amp;gt;, так как в запросах используется не более &amp;lt;tex&amp;gt;2m&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Время работы: &amp;lt;tex&amp;gt;O(m \log m \log n) = O(m \log^2 m)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
== Реализация на C++ ==&lt;br /&gt;
 '''#include''' &amp;lt;bits/stdc++.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''using''' '''namespace''' std;&lt;br /&gt;
 '''typedef''' pair &amp;lt; '''int''' , '''int''' &amp;gt; ipair;&lt;br /&gt;
 '''const''' '''int''' N = 100321;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// СНМ&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''int''' dsuP[N], dsuR[N];&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// В этот массив записываются все изменения СНМ, чтобы их можно откатить&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При изменении какого-то значения в СНМ в hist записывается пара &amp;lt; указатель, старое значение &amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 vector &amp;lt; pair &amp;lt; '''int'''*, '''int''' &amp;gt; &amp;gt; hist;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для элемента из СНМ возвращает корень дерева, в котором он находится&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''int''' dsuRoot('''int''' v)&lt;br /&gt;
 {&lt;br /&gt;
     '''while''' (dsuP[v] != -1)&lt;br /&gt;
         v = dsuP[v];&lt;br /&gt;
     '''return''' v;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Объединяет два множества. Используется ранговая эвристика.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При любом изменении содержимого массивов dsuP и dsuR&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// в hist записывается адрес и старое значение&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''void''' dsuMerge('''int''' a, '''int''' b)&lt;br /&gt;
 {&lt;br /&gt;
     a = dsuRoot(a);&lt;br /&gt;
     b = dsuRoot(b);&lt;br /&gt;
     '''if''' (a == b)&lt;br /&gt;
         '''return''';&lt;br /&gt;
     '''if''' (dsuR[a] &amp;gt; dsuR[b])&lt;br /&gt;
     {&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuP[b], dsuP[b]);&lt;br /&gt;
         dsuP[b] = a;&lt;br /&gt;
     } '''else''' '''if''' (dsuR[a] &amp;lt; dsuR[b])&lt;br /&gt;
     {&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuP[a], dsuP[a]);&lt;br /&gt;
         dsuP[a] = b;&lt;br /&gt;
     } '''else'''&lt;br /&gt;
     {&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuP[a], dsuP[a]);&lt;br /&gt;
         hist.emplace_back(&amp;amp;dsuR[b], dsuR[b]);&lt;br /&gt;
         dsuP[a] = b;&lt;br /&gt;
         ++dsuR[b];&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 '''struct''' Query&lt;br /&gt;
 {&lt;br /&gt;
     '''int''' t, u, v;&lt;br /&gt;
     bool answer;&lt;br /&gt;
 };&lt;br /&gt;
 '''int''' n, m;&lt;br /&gt;
 Query q[N];&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Дерево отрезков, в каждой вершине которого хранится список рёбер&amp;lt;/font&amp;gt;&lt;br /&gt;
 vector &amp;lt; ipair &amp;gt; t[N*4];&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Эта функция добавляет ребро на отрезок&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// [l r] - отрезок, на который добавляется ребро&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// uv - ребро, c - текущая вершина дерева отрезков,&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// [cl cr] - отрезок текущей вершины дерева отрезков&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''void''' addEdge('''int''' l, '''int''' r, ipair uv, '''int''' c, '''int''' cl, '''int''' cr)&lt;br /&gt;
 {&lt;br /&gt;
     '''if''' (l &amp;gt; cr || r &amp;lt; cl)&lt;br /&gt;
         '''return''';&lt;br /&gt;
     '''if''' (l &amp;lt;= cl &amp;amp;&amp;amp; cr &amp;lt;= r)&lt;br /&gt;
     {&lt;br /&gt;
         t[c].push_back(uv);&lt;br /&gt;
         '''return''';&lt;br /&gt;
     }&lt;br /&gt;
     '''int''' mid = (cl + cr) / 2;&lt;br /&gt;
     addEdge(l, r, uv, c*2+1, cl, mid);&lt;br /&gt;
     addEdge(l, r, uv, c*2+2, mid+1, cr);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Обход дерева отрезков в глубину&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''void''' go('''int''' c, '''int''' cl, '''int''' cr)&lt;br /&gt;
 {&lt;br /&gt;
     '''int''' startSize = hist.size();&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем рёбра при входе в вершину&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' (ipair uv : t[c])&lt;br /&gt;
         dsuMerge(uv.first, uv.second);&lt;br /&gt;
 &lt;br /&gt;
     '''if''' (cl == cr)&lt;br /&gt;
     {&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Если эта вершина - лист, то отвечаем на запрос&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' (q[cl].t == 3)&lt;br /&gt;
             q[cl].answer = (dsuRoot(q[cl].u) == dsuRoot(q[cl].v));&lt;br /&gt;
     } '''else''' {&lt;br /&gt;
         '''int''' mid = (cl + cr) / 2;&lt;br /&gt;
         go(c*2+1, cl, mid);&lt;br /&gt;
         go(c*2+2, mid+1, cr);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Откатываем изменения СНМ&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' (('''int''')hist.size() &amp;gt; startSize)&lt;br /&gt;
     {&lt;br /&gt;
         *hist.back().first = hist.back().second;&lt;br /&gt;
         hist.pop_back();&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 '''int''' main()&lt;br /&gt;
 {&lt;br /&gt;
     ios::sync_with_stdio('''false''');&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Формат входных данных:&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// n и m, затем в m строках запросы: по три числа t, u, v&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// t - тип (1 - добавить ребро, 2 - удалить, 3 - принадлежат ли одной компоненте)&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Нумерация вершин с нуля&amp;lt;/font&amp;gt;&lt;br /&gt;
     cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;&lt;br /&gt;
     '''for''' ('''int''' i = 0; i &amp;lt; n; ++i) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализация СНМ&amp;lt;/font&amp;gt;&lt;br /&gt;
         dsuP[i] = -1;&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// В этом массиве для каждого ещё не удалённого ребра хранится&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// на каком запросе оно было создано&amp;lt;/font&amp;gt;&lt;br /&gt;
     set &amp;lt; pair &amp;lt; ipair, '''int''' &amp;gt; &amp;gt; edges;&lt;br /&gt;
     '''for''' ('''int''' i = 0; i &amp;lt; m; ++i)&lt;br /&gt;
     {&lt;br /&gt;
         cin &amp;gt;&amp;gt; q[i].t &amp;gt;&amp;gt; q[i].u &amp;gt;&amp;gt; q[i].v;&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Поскольку рёбра неориентированные, u v должно означать то же самое, что и v u&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' (q[i].u &amp;gt; q[i].v) swap(q[i].u, q[i].v);&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При добавлении ребра кладём его в set&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' (q[i].t == 1)&lt;br /&gt;
             edges.emplace(ipair(q[i].u, q[i].v), i);&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При удалении ребра берём из set время его добавления - так мы узнаём отрезок заросов,&amp;lt;/font&amp;gt;&lt;br /&gt;
         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// на котором оно существует. Если есть несколько одинаковых рёбер, можно брать любое.&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''else''' '''if''' (q[i].t == 2)&lt;br /&gt;
         {&lt;br /&gt;
             '''auto''' iter = edges.lower_bound(make_pair(ipair(q[i].u, q[i].v), 0));&lt;br /&gt;
             addEdge(iter-&amp;gt;second, i, iter-&amp;gt;first, 0, 0, m - 1);&lt;br /&gt;
             edges.erase(iter);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Обрабатываем рёбра, которые не были удалены&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' ('''auto''' e : edges)&lt;br /&gt;
         addEdge(e.second, m - 1, e.first, 0, 0, m - 1);&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Запускаем dfs по дереву отрезков&amp;lt;/font&amp;gt;&lt;br /&gt;
     go(0, 0, m - 1);&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выводим ответ.&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// При обходе дерева отрезков запросы обрабатываются в том же порядке, в котором они даны,&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// поэтому ответ можно выводить прямо в go без заполнения answer&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' ('''int''' i = 0; i &amp;lt; m; ++i)&lt;br /&gt;
         '''if''' (q[i].t == 3)&lt;br /&gt;
         {&lt;br /&gt;
             '''if''' (q[i].answer)&lt;br /&gt;
                 cout &amp;lt;&amp;lt; &amp;quot;YES\n&amp;quot;;&lt;br /&gt;
             '''else'''&lt;br /&gt;
                 cout &amp;lt;&amp;lt; &amp;quot;NO\n&amp;quot;;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
     '''return''' 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Замечания ==&lt;br /&gt;
* Дерево отрезков можно строить не на всех запросах, а только на запросах третьего типа. Это даст выигрыш по скорости и памяти, особенно если таких запросов немного по сравнению с общим числом запросов.&lt;br /&gt;
* Помимо проверки, лежат ли две вершины в одной компоненте связности, можно получать и другую информацию, которую можно получить из СНМ, напрмер:&lt;br /&gt;
** Размер компоненты связности, которая содержит вершину &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Количество компонент связности&lt;br /&gt;
* Эту идею можно использовать и для других задач. Вместо СНМ можно использовать любую структуру данных, в которую можно добавлять, но не удалять.&lt;br /&gt;
** Например, динамический рюкзак: добавлять предмет в него можно за &amp;lt;tex&amp;gt;O(w)&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; {{---}} максимальный вес), а удалять нельзя. Аналогично тому, как в dynamic connectivity offline добавляются и удаляются рёбра, можно удалять элементы из рюкзака.&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;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63014</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63014"/>
				<updated>2017-12-25T14:23:58Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Описание в псевдокоде */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины незамужние.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m ещё не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&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;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&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;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;O(1)&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^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63013</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63013"/>
				<updated>2017-12-25T14:09:49Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Обобщения задачи */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины не замужем.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m еще не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&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;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&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;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;O(1)&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^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;ref&amp;gt;https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате Задача о соседях по комнате&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63012</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63012"/>
				<updated>2017-12-25T13:16:56Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины не замужем.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m еще не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&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;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&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;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;O(1)&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^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;
[https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате задача о соседях по комнате])&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
* [http://kek.ksu.ru/eos/Lerner/KnuthRu.pdf Устойчивость супружеских пар и другие комбинаторные задачи - Казанский государственный университет]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63007</id>
		<title>Задача об устойчивом паросочетании</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1_%D1%83%D1%81%D1%82%D0%BE%D0%B9%D1%87%D0%B8%D0%B2%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8&amp;diff=63007"/>
				<updated>2017-12-24T18:15:23Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition='''Устойчивое паросочетание''' (англ. ''stable matching'') — [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях| паросочетание]] без неустойчивых пар.&lt;br /&gt;
}}&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Найти полное устойчивое паросочетание между элементами двух множеств размера &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, имеющими свои предпочтения.}}&lt;br /&gt;
&lt;br /&gt;
== Основная задача ==&lt;br /&gt;
&lt;br /&gt;
Есть &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; женщин. Они обладают следующими особенностями:&lt;br /&gt;
# Каждый человек оценивает лишь людей противоположного пола (все гетеросексуальны);&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;
|definition = &lt;br /&gt;
 Пара &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; называется '''неустойчивой''' (англ. ''unstable pair''), если:&lt;br /&gt;
# В паросочетании есть пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\langle B, b\rangle&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;)&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; ''привлекательней'', чем &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм Гейла-Шепли ==&lt;br /&gt;
&lt;br /&gt;
Решение задачи было описано в 1962 году математиками Девидом Гейлом (Университета Брауна) и Ллойдом Шепли (Принстонский университет) в статье «Поступление в колледж и стабильность браков» (College admissions and the stability of marriage) в журнале American Mathematical Monthly&lt;br /&gt;
&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/American_Mathematical_Monthly American Mathematical Monthly 69, 9-14, 1962.&amp;lt;/ref&amp;gt;. Набор правил, следование которым всегда приводит к образованию стабильных пар, получил название алгоритма Гейла-Шепли или «алгоритма отложенного согласия» (алгоритм предложи-и-откажи).&lt;br /&gt;
&lt;br /&gt;
=== Интуитивное описание ===&lt;br /&gt;
&lt;br /&gt;
# Мужчины делают предложение наиболее предпочитаемой женщине.&lt;br /&gt;
# Каждая женщина из всех поступивших предложений выбирает наилучшее и отвечает на него «может быть» (помолвка), на все остальные отвечает «нет» (отказ).&lt;br /&gt;
# Мужчины, получившие отказ, обращаются к следующей женщине из своего списка предпочтений, мужчины, получившие ответ «может быть», ничего не делают.&lt;br /&gt;
# Если женщине пришло предложение лучше предыдущего, то она прежнему претенденту (которому ранее сказала «может быть») говорит «нет», а новому претенденту говорит «может быть».&lt;br /&gt;
# Шаги 1-4 повторяются, пока у всех мужчин не исчерпается список предложений, в этот момент женщины отвечают «да» на те предложения «может быть», которые у них есть в настоящий момент.&lt;br /&gt;
&lt;br /&gt;
=== Описание в псевдокоде ===&lt;br /&gt;
&lt;br /&gt;
   Изначально все мужчины не женаты и все женщины не замужем.&lt;br /&gt;
   '''while''' Существует m &amp;lt;- некоторый свободный мужчина, не делавший предложения всем женщинам&lt;br /&gt;
      w &amp;lt;- первая женщина из списка m, которой m еще не делал предложения&lt;br /&gt;
      '''if''' w свободна&lt;br /&gt;
         помечаем m и w помолвленными&lt;br /&gt;
      '''else if''' w предпочитает m своему &amp;quot;текущему&amp;quot; жениху m'&lt;br /&gt;
         помечаем m и w помолвленными, m' — свободным&lt;br /&gt;
      '''else'''&lt;br /&gt;
         w отказывает m&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation1&lt;br /&gt;
|about=Наблюдение 1&lt;br /&gt;
|statement=Мужчины делают предложения женщинам в порядке убывания симпатии.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=observation2&lt;br /&gt;
|about=Наблюдение 2&lt;br /&gt;
|statement=Как только женщина была помолвлена, она не может стать непомолвленной, она может только улучшить свой выбор (сказать «может быть» более предпочтительному кандидату).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для начала покажем, что алгоритм завершит свою работу.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|about=Лемма 1&lt;br /&gt;
|statement=&lt;br /&gt;
	Алгоритм завершается после максимум &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; итераций цикла &amp;lt;tex&amp;gt;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
	На каждой итерации мужчина делает предложение очередной женщине. Но всего может быть не более &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt; предложений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Теперь покажем, что по завершении алгоритма задача будет решена.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2&lt;br /&gt;
|about=Лемма 2&lt;br /&gt;
|statement=&lt;br /&gt;
	Все мужчины и женщины будут заняты.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим, что некоторый мужчина (&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;) не женат по завершении алгоритма. Тогда некоторая женщина (&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;) не замужем. По [[#observation2|наблюдению 2]], &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не получала предложений. Но &amp;lt;tex&amp;gt;A&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;
|id=lemma3&lt;br /&gt;
|about=Лемма 3&lt;br /&gt;
|statement=&lt;br /&gt;
	После завершения алгоритма не будет неустойчивых пар.&lt;br /&gt;
|proof=&lt;br /&gt;
Предположим &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; — женщины; &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;) — нестабильная пара в паросочетании, найденном алгоритмом Гейла-Шепли. Рассмотрим два случая:&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не делал предложения &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;\langle A, b\rangle&amp;lt;/tex&amp;gt; — устойчивая пара.&lt;br /&gt;
# &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; делал предложение &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;. Тогда был такой момент, когда &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; отказала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; находит &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; более привлекательным, чем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Снова получается, что &amp;lt;tex&amp;gt;\langle A, b\rangle&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;\mathrm{\mathbf{while}}&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;O(1)&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^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Анализ полученного алгоритмом паросочетания ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм Гейла-Шепли гарантирует, что будет найдено некоторое решение задачи. Но решений может быть более одного. Зададимся вопросом, какими свойствами обладает решение, найденное алгоритмом.&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma4&lt;br /&gt;
|about=man-optimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наилучшее для мужчин (каждый мужчина получает в жены женщину, наилучшую из всех возможных при условии корректности решения).&lt;br /&gt;
|proof=&lt;br /&gt;
Если женщина &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; вычёркивается из списка предпочтений мужчины &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то ни одно устойчивое паросочетание не будет содержать пары &amp;lt;tex&amp;gt;\langle A, a\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма &lt;br /&gt;
|id=lemma5&lt;br /&gt;
|about=woman-pessimality&lt;br /&gt;
|statement=&lt;br /&gt;
	Из всех возможных решений алгоритмом Гейла-Шепли будет найдено решение, наихудшее для женщин.&lt;br /&gt;
|proof= &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; — мужчины; &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;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;B&amp;lt;/tex&amp;gt; женат на &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим, &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt;  — стабильная пара в паросочетании &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;, найденном алгоритмом Гейла-Шепли, но &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; не самый худший выбор для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;. Тогда существует стабильная пара в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, в которой &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; замужем за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;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;A&amp;lt;/tex&amp;gt; в паросочетании &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Получается &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; считает &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; более привлекательной, чем &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;. Соответственно &amp;lt;tex&amp;gt;\langle A, c\rangle&amp;lt;/tex&amp;gt; {{---}} нестабильная пара в паросочетании &amp;lt;tex&amp;gt;S&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;
[https://ru.wikipedia.org/wiki/Задача_о_соседях_по_комнате задача о соседях по комнате])&lt;br /&gt;
&lt;br /&gt;
Случай же, когда у нас есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; мужчин и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; женщин (&amp;lt;tex&amp;gt;N \neq M&amp;lt;/tex&amp;gt;) легко сводится к описанной выше задаче. Рассмотрим &amp;lt;tex&amp;gt;M &amp;gt; N&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;M &amp;lt; N&amp;lt;/tex&amp;gt; аналогично). Добавим &amp;lt;tex&amp;gt;M - N&amp;lt;/tex&amp;gt; фиктивных мужчин, которые являются ''наименее привлекательными'' с точки зрения каждой из женщин. Тогда если в найденном алгоритмом Гейла-Шепли паросочетании некоторая женщина будет замужем за таким фиктивным мужчиной, это будет де-факто означать, что она осталась не замужем.&lt;br /&gt;
&lt;br /&gt;
Также интересна задача о выборе учебного заведения: вместо множества мужчин введем множество университетов, а вместо множества женщин — множество кандидатов, подающих заявления на поступление. Причем в каждом университете есть квота на количество студентов, которое университет может принять. Задача очевидно сводится к основной добавлением &amp;lt;tex&amp;gt;(K-1)&amp;lt;/tex&amp;gt; &amp;quot;филиалов&amp;quot; для каждого университета (&amp;lt;tex&amp;gt;K&amp;lt;/tex&amp;gt; — квота). И добавлением фиктивного университета (поступление в который означает, что кандидату придется попробовать поступить через год).&lt;br /&gt;
&lt;br /&gt;
== Применения в реальной жизни ==&lt;br /&gt;
&lt;br /&gt;
Задача о нахождении устойчивого паросочетания и её решение имеют множество применений в реальной жизни, лишь некоторые из них:&lt;br /&gt;
* Распределение студентов по коллеждам в США&lt;br /&gt;
* Распределение интернов по больницам&lt;br /&gt;
* Распределение донорских органов по нуждающимся в них людям&lt;br /&gt;
&lt;br /&gt;
Решение данной задачи было отмечено при вручении Нобелевской премии по экономике в 2012 году за «теорию стабильного распределения и практическое применение рыночных моделей». Её получили один из создателей алгоритма, Ллойд Шепли, а также Элвин Рот, во многом развивший исследования Ллойда Шепли и Дэвида Гейла. Сам Гейл не был удостоен премии, вероятно, лишь в силу того, что умер в 2008 году.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях|Паросочетания]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.princeton.edu/courses/archive/spring05/cos423/lectures/01stable-matching.pdf Stable matching, Prinston lecture's presentation]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Stable_marriage_problem Stable marriage problem]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BC%D0%B0%D1%80%D1%8C%D1%8F%D0%B6%D0%B5 Задача о марьяже]&lt;br /&gt;
* [http://ge.tt/api/1/files/4LU3zaD1/0/blob?download Устойчивость супружеских пар и другие комбинаторные задачи (Статья Дональда Кнута)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о паросочетании]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=1pi1sumwu&amp;diff=62750</id>
		<title>1pi1sumwu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=1pi1sumwu&amp;diff=62750"/>
				<updated>2017-12-17T13:00:29Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt; 1 \mid p_{i}=1 \mid \sum\nolimits w_iU_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
А нельзя ли обозвать как-то по-другому?&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Дано &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt; станок. Для каждой работы известны её дедлайн &amp;lt;tex&amp;gt; d_{i} &amp;lt;/tex&amp;gt; и вес &amp;lt;tex&amp;gt; w_{i} &amp;lt;/tex&amp;gt;. Время выполнения всех работ &amp;lt;tex&amp;gt; p_i &amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;. Требуется минимизировать &amp;lt;tex&amp;gt;\sum w_{i} U_{i}&amp;lt;/tex&amp;gt;, то есть суммарный вес всех просроченных работ.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Идея алгоритма состоит в том, чтобы на шаге &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; строить оптимальное расписание для первых &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; работ с наименьшими дедлайнами.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что работы отсортированны в порядке неуменьшения их дедлайнов.&lt;br /&gt;
Пусть мы уже рассмотрели первые &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; работ, тогда множество &amp;lt;tex&amp;gt; S_{k} &amp;lt;/tex&amp;gt; содержит только те работы, которые мы успеваем выполнить в порядке неуменьшения их дедлайнов при оптимальном составлении расписания . Рассмотрим работу &amp;lt;tex&amp;gt; k + 1 &amp;lt;/tex&amp;gt;. Если мы успеваем выполнить данную работу до ее дедлайна, то добавим ее во множество &amp;lt;tex&amp;gt; S_{k} &amp;lt;/tex&amp;gt;, тем самым получив &amp;lt;tex&amp;gt; S_{k + 1} &amp;lt;/tex&amp;gt;. Если же &amp;lt;tex&amp;gt; k + 1 &amp;lt;/tex&amp;gt; работу выполнить до дедлайна мы не успеваем, то найдем в &amp;lt;tex&amp;gt; S_{k} &amp;lt;/tex&amp;gt; работу &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; с наименьшим весом &amp;lt;tex&amp;gt; w_{l} &amp;lt;/tex&amp;gt; и заменим ее на работу &amp;lt;tex&amp;gt; k + 1 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, рассмотрев все работы, мы получим &amp;lt;tex&amp;gt; S_{n} &amp;lt;/tex&amp;gt; {{---}} множество работ, которые мы успеваем выполнить до наступления их дедлайнов, причем вес просроченных работ будет наименьшим. От порядка выполнения просроченных работ ничего не зависит, поэтому расположить в расписании их можно произвольным образом.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
Предполагаем, что перед началом выполнения алгоритма выполняется, что &amp;lt;tex&amp;gt; 1 \leqslant d_{1} \leqslant d_{2} \leqslant ... \leqslant d_{n} &amp;lt;/tex&amp;gt;. Все работы, дедлайн которых равен &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt;, мы в любом случае выполнить без штрафа не успеем, поэтому их изначально можно отнести к просроченным.&lt;br /&gt;
&lt;br /&gt;
В псевдокоде используются переменные:&lt;br /&gt;
*&amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; {{---}} множество непросроченных работ&lt;br /&gt;
*&amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; {{---}} текущее время&lt;br /&gt;
&lt;br /&gt;
 '''Set'''&amp;lt;'''int'''&amp;gt; p1sumwu('''int''' &amp;lt;tex&amp;gt;w[n]&amp;lt;/tex&amp;gt;, '''int''' &amp;lt;tex&amp;gt;d[n]&amp;lt;/tex&amp;gt;):&lt;br /&gt;
   '''int''' &amp;lt;tex&amp;gt; t = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''Set'''&amp;lt;'''int'''&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\{\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''for''' &amp;lt;tex&amp;gt; i = 1 &amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt; s = s \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''if''' &amp;lt;tex&amp;gt; d_{i}  \geqslant t &amp;lt;/tex&amp;gt;     &lt;br /&gt;
         &amp;lt;tex&amp;gt; t = t + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''else'''&lt;br /&gt;
         найти такое &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt; w_{k} = \min \{ w_{j} \mid j \in s\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; s = s \setminus \{k\} &amp;lt;/tex&amp;gt;    &lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Доказательство корректности ==&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Алгоритм строит корректное расписание.&lt;br /&gt;
|proof=Если мы успеваем выполнить очередную работу, то, очевидно, от ее добавления, расписание не может стать некорректным. В противном случае мы пытаемся заменить одну работу из множества &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; на текущую. Но это так же не может сделать наше расписание некорректным. Это следует из того, что мы рассматриваем работы в порядке неуменьшениях их дедлайнов. Пусть мы заменяем работу &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Но &amp;lt;tex&amp;gt; d_{k} \leqslant d_{i} &amp;lt;/tex&amp;gt;, следовательно, если мы успевали выполнить работу &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, то успеем выполнить и работу &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Построенное данным алгоритмом расписание оптимально.&lt;br /&gt;
|proof=Пусть &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt; множество непросроченных работ в оптимальном расписании. Также пусть &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; {{---}} первая работа из множества &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;, которая не входит в &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; {{---}} первая работа из &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt;, не содержащаяся в &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;. Мы можем предполагать существование этих работ, потому что &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt; не может содержать &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; как подмножество, иначе это противоречило бы построению &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;. С другой стороны, если &amp;lt;tex&amp;gt; S^* \subseteq S &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; должно быть тоже оптимальным, и правильность алгоритма доказана.&lt;br /&gt;
&lt;br /&gt;
Для доказательства покажем, что мы можем заменить работу &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; в оптимальном расписании, не увеличивая минимизируемую функцию.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим два случая:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt; l &amp;lt; k &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Так как работа &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; не содержится в &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;, то либо она не была добавлена при ее рассмотрении, либо была заменена работой, рассмотренной позднее. В любом случае это означает, что &amp;lt;tex&amp;gt; w_{k} \leqslant w_{l} &amp;lt;/tex&amp;gt;. Так же по определению &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt; i \in S^* : i &amp;lt; k &amp;lt;/tex&amp;gt; должны содержаться и в &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;. Но тогда заменив в оптимальном расписании &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt;, мы сохраним корректность расписания и не увеличим минимизируемую функцию.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt; k &amp;lt; l &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Так как мы рассматриваем работы в порядке неубывания их дедлайнов, то, следовательно, &amp;lt;tex&amp;gt; d_{k} \leqslant d_{l} &amp;lt;/tex&amp;gt;, и замена работы &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; в оптимальном расписании &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt; не может сделать его некорректным. Тогда для доказательства нам осталось показать, что &amp;lt;tex&amp;gt; w_{k} \leqslant w_{l} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt; k_{i_{0}} = k &amp;lt;/tex&amp;gt; {{---}} работа, замененная работой &amp;lt;tex&amp;gt; i_{0} &amp;lt;/tex&amp;gt; в процессе построения &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;, и пусть &amp;lt;tex&amp;gt; k_{i_{1}}, ..., k_{i_{r}} &amp;lt;/tex&amp;gt; {{---}} последовательность работ, которые были исключены из &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; после замены &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, причем работа &amp;lt;tex&amp;gt; k_{i_{v}} &amp;lt;/tex&amp;gt; была заменена работой &amp;lt;tex&amp;gt; i_{v} &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; i_{0} &amp;lt; i_{1} &amp;lt; ... &amp;lt; i_{r} &amp;lt;/tex&amp;gt;. Будем говорить, что &amp;quot;работа &amp;lt;tex&amp;gt; i_{v} &amp;lt;/tex&amp;gt; подавляет &amp;lt;tex&amp;gt; i_{m} &amp;lt;/tex&amp;gt;&amp;quot;, где &amp;lt;tex&amp;gt; m &amp;lt; v &amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt; k_{i_{v}} \leqslant i_{m} &amp;lt;/tex&amp;gt;. В таком случае получаем, что &amp;lt;tex&amp;gt; w_{k_{i_{v}}} \geqslant w_{k_{i_{m}}}&amp;lt;/tex&amp;gt;, потому что в противном случае работа &amp;lt;tex&amp;gt; k_{i_{v}} &amp;lt;/tex&amp;gt; была бы исключена из &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; раньше чем &amp;lt;tex&amp;gt; k_{i_{m}} &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:Если в последовательности &amp;lt;tex&amp;gt; i_{0} &amp;lt; i_{1} &amp;lt; ... &amp;lt; i_{r} &amp;lt;/tex&amp;gt; существует подпоследовательность &amp;lt;tex&amp;gt; j_{0} = i_{0} &amp;lt; j_{1} &amp;lt; ... &amp;lt; j_{s} &amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt; j_{v + 1} &amp;lt;/tex&amp;gt; подавляет &amp;lt;tex&amp;gt; j_{v} &amp;lt;/tex&amp;gt; для всех &amp;lt;tex&amp;gt; v = 0,1, ..., s - 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j_{s - 1} &amp;lt; l \leqslant j_{s} &amp;lt;/tex&amp;gt;, то получаем, что &amp;lt;tex&amp;gt; w_{l} \geqslant w_{k_{j_{s}}} \geqslant ... \geqslant w_{k_{j_{0}}} = w_{k} &amp;lt;/tex&amp;gt;, что доказывает оптимальность расписания &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Покажем, что отсутствие такой подпоследовательности приведет нас к противоречию, из чего будет следовать ее существование.&lt;br /&gt;
&lt;br /&gt;
:Предположим, что такой подпоследовательности не существует. Тогда найдем наименьшее &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; такое, что не существует работы &amp;lt;tex&amp;gt; i_{v} : v &amp;gt; t &amp;lt;/tex&amp;gt;, которая бы подавляла работу &amp;lt;tex&amp;gt; i_{t} &amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt; i_{t} &amp;lt;/tex&amp;gt; было бы меньше &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt;. По определению &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; i_{t} &amp;lt;/tex&amp;gt; и из факта, что &amp;lt;tex&amp;gt; i_{t} &amp;lt; l &amp;lt;/tex&amp;gt;, получаем, что после добавления во множество &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; работы &amp;lt;tex&amp;gt; i_{t} &amp;lt;/tex&amp;gt;, ни одна из работ, рассмотренных ранее, не будет удалена из &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;, а так же все эти работы содержатся и в оптимальном расписании &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt;, поскольку &amp;lt;tex&amp;gt; i_t &amp;lt; l &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt; S_t &amp;lt;/tex&amp;gt; это множество &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; после замены работы &amp;lt;tex&amp;gt; k_{i_t} &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; i_t &amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt; k_{i_t} &amp;gt; k &amp;lt;/tex&amp;gt;, то в оптимальном расписании &amp;lt;tex&amp;gt; S^* &amp;lt;/tex&amp;gt; мы можем заменить работу &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; k_{i_t} &amp;lt;/tex&amp;gt;, поскольку &amp;lt;tex&amp;gt; d_{k_{i_t}} \geqslant d_k &amp;lt;/tex&amp;gt;. Но так как &amp;lt;tex&amp;gt; S_t \subset S^* &amp;lt;/tex&amp;gt;, то все работы из множества &amp;lt;tex&amp;gt; S_t \cup \{k_{i_t}\} &amp;lt;/tex&amp;gt; могут быть выполнены до их дедлайнов, что противоречит построению &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt; k_{i_t} &amp;lt; k &amp;lt;/tex&amp;gt;. Тогда аналогично предыдущему случаю получаем, что все работы из множества &amp;lt;tex&amp;gt; S_t \cup \{k\} &amp;lt;/tex&amp;gt; могут быть выполнены вовремя. Кроме того, все работы из &amp;lt;tex&amp;gt; \{ j \in S_t | j &amp;lt; k \} \cup \{k_{i_t}\} &amp;lt;/tex&amp;gt; так же могут быть выполнены вовремя, что следует из построения &amp;lt;tex&amp;gt; S_t &amp;lt;/tex&amp;gt;. Но тогда получается, что все работы и из множества &amp;lt;tex&amp;gt; S_t \cup \{k_{i_t}\} &amp;lt;/tex&amp;gt; так же могут быть выполнены вовремя, что опять приводит нас к противоречию с построением &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Время работы ==&lt;br /&gt;
Время работы алгоритма зависит от того, насколько быстро мы будем добавлять и удалять работы из множества &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;, а также как быстро мы будем искать работу с минимальным весом. Если в качестве множества &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt; использовать структуру данных, умеющую выполнять данные операции за &amp;lt;tex&amp;gt; O(\log n) &amp;lt;/tex&amp;gt;, то время работы всего алгоритма будет составлять &amp;lt;tex&amp;gt; O(n\log n) &amp;lt;/tex&amp;gt;. Например, такими структурами данных являются [[Двоичная куча | двоичная куча]] и [[Красно-черное дерево | красно-черное дерево]].&lt;br /&gt;
&lt;br /&gt;
==Cм. также ==&lt;br /&gt;
* [[1ripipsumwu|&amp;lt;tex&amp;gt; 1 \mid r_i,p_i=p \mid \sum w_i U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Ppi1sumwu|&amp;lt;tex&amp;gt;P \mid p_i=1 \mid \sum w_i U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iU_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 96 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</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_%D0%90%D1%85%D0%BE-%D0%9A%D0%BE%D1%80%D0%B0%D1%81%D0%B8%D0%BA&amp;diff=62338</id>
		<title>Алгоритм Ахо-Корасик</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%90%D1%85%D0%BE-%D0%9A%D0%BE%D1%80%D0%B0%D1%81%D0%B8%D0%BA&amp;diff=62338"/>
				<updated>2017-11-22T18:35:45Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Пример реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дан набор строк в алфавите размера &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; суммарной длины &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Необходимо найти для каждой строки все ее вхождения в текст.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
=== Шаг 1. Построение бора ===&lt;br /&gt;
Строим [[Бор|бор]] из строк.&amp;lt;br /&amp;gt;&lt;br /&gt;
Построение выполняется за время &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; {{---}} суммарная длина строк.&lt;br /&gt;
&lt;br /&gt;
====Пример построенного бора====&lt;br /&gt;
Бор для набора строк &amp;lt;tex&amp;gt; \{ \textbf{he},\ \textbf{she},\ \textbf{his},\ \textbf{hers}\} &amp;lt;/tex&amp;gt;:&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:Бор.jpg‎]]&lt;br /&gt;
&lt;br /&gt;
=== Шаг 2. Преобразование бора ===&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;[u]&amp;lt;/tex&amp;gt; слово, приводящее в вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в боре.&amp;lt;br /&amp;gt;&lt;br /&gt;
Узлы бора можно понимать как состояния [[Детерминированные_конечные_автоматы | автомата]], а корень как начальное состояние.&amp;lt;br /&amp;gt;&lt;br /&gt;
Узлы бора, в которых заканчиваются строки, становятся терминальными.&amp;lt;br /&amp;gt;&lt;br /&gt;
Для переходов по автомату заведём в узлах несколько функций:&amp;lt;br /&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{parent}(u)&amp;lt;/tex&amp;gt; {{---}} возвращает родителя вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;;&amp;lt;br /&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;\pi(u) = \delta(\pi(\mathrm{parent}(u)), c)&amp;lt;/tex&amp;gt; {{---}} '''суффиксная ссылка''', и существует переход из  &amp;lt;tex&amp;gt;\mathrm{parent}(u)&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; по символу &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;;&amp;lt;br /&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;\delta(u, c) = &lt;br /&gt;
  \begin{cases}&lt;br /&gt;
     v,                 &amp;amp;\text{if $v$ is son by symbol $c$ in trie;}\\&lt;br /&gt;
     root,              &amp;amp;\text{if $u$ is root and $u$ has no child by symbol $c$ in trie}\\&lt;br /&gt;
     \delta(\pi(u), c), &amp;amp;\text{else.}&lt;br /&gt;
   \end{cases}&amp;lt;/tex&amp;gt; {{---}} функция перехода.&lt;br /&gt;
Мы можем понимать рёбра бора как переходы в автомате по соответствующей букве. Однако одними только рёбрами бора нельзя ограничиваться. Если мы пытаемся выполнить переход по какой-либо букве, а соответствующего ребра в боре нет, то мы тем не менее должны перейти в какое-то состояние. Для этого нам и нужны суффиксные ссылки.&lt;br /&gt;
&amp;lt;br&amp;gt; Суффиксная ссылка &amp;lt;tex&amp;gt;\pi(u) = v&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;[v]&amp;lt;/tex&amp;gt; {{---}} максимальный суффикс &amp;lt;tex&amp;gt;[u]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[v]\neq[u]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Функции перехода и суффиксные ссылки можно найти либо алгоритмом [[Обход в глубину, цвета вершин | обхода в глубину]] с ленивыми вычислениями, либо с помощью алгоритма [[Обход в ширину | обхода в ширину]].&lt;br /&gt;
&lt;br /&gt;
Из определений выше можно заметить два следующих факта:&lt;br /&gt;
* функция перехода определена через суффиксную ссылку, а суффиксная ссылка {{---}} через функию переходов;&lt;br /&gt;
* для построения суффиксных ссылок небходимо знать информацию только выше по бору от текущей вершины до корня.&lt;br /&gt;
Это позволяет реализовать функции поиска переходов по символу и суффиксных ссылок ленивым образом при помощи взаимной рекурсии.&lt;br /&gt;
&lt;br /&gt;
==== Пример автомата Ахо-Корасик ====&lt;br /&gt;
[[Файл:axo.jpg]]&amp;lt;br /&amp;gt;&lt;br /&gt;
Пунктиром обозначены суффиксные ссылки. Из вершин, для которых они не показаны, суффиксные ссылки идут в корень.&lt;br /&gt;
&lt;br /&gt;
Суффиксная ссылка для каждой вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; — это вершина, в которой оканчивается наидлиннейший собственный суффикс строки, соответствующей вершине &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. Единственный особый случай — корень бора: для удобства суффиксную ссылку из него проведём в себя же. Например, для вершины &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; с соответствующей ей строкой &amp;lt;tex&amp;gt;&amp;quot;she&amp;quot;&amp;lt;/tex&amp;gt; максимальным подходящим суффиксом является строка &amp;lt;tex&amp;gt;&amp;quot;he&amp;quot;&amp;lt;/tex&amp;gt;. Видим, что такая строка заканчивается в вершине &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. Следовательно суффиксной ссылкой вершины для &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; является вершина &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
===Шаг 3. Построение сжатых суффиксных ссылок ===&lt;br /&gt;
При построении автомата может возникнуть такая ситуация, что ветвление есть не на каждом символе. Тогда можно маленький бамбук заменить одним ребром. Для этого и используются сжатые суффиксные ссылки.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;up(u) = &lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    \pi(u),     &amp;amp;\text{if $\pi(u)$ is terminal;}\\&lt;br /&gt;
    \varnothing,&amp;amp;\text{if $\pi(u)$ is root;}\\&lt;br /&gt;
    up(\pi(u)), &amp;amp;\text{else.}&lt;br /&gt;
  \end{cases}&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
где &amp;lt;tex&amp;gt;up&amp;lt;/tex&amp;gt; {{---}} сжатая суффиксная ссылка, т.е. ближайшее допускающее состояние (терминал) перехода по суффиксным ссылкам. Аналогично обычным суффиксным ссылкам сжатые суффиксные ссылки могут быть найдены при помощи ленивой рекурсии.&lt;br /&gt;
&lt;br /&gt;
== Использование автомата ==&lt;br /&gt;
Теперь нужно сказать немного слов о том, как мы будем использовать наш автомат. По очереди просматриваем символы текста. Для очередного символа &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; переходим из текущего состояния &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в состояние, которое вернёт функция &amp;lt;tex&amp;gt;\delta(u, c)&amp;lt;/tex&amp;gt;. Оказавшись в новом состоянии, отмечаем по сжатым суффиксным ссылкам строки, которые нам встретились и их позицию (если требуется). Если новое состояние является терминалом, то соответствующие ему строки тоже отмечаем.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже представлена реализация некоторых функций (используется ленивая рекурсия).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} размер алфавита.&lt;br /&gt;
&lt;br /&gt;
'''Структура вершины:'''&lt;br /&gt;
 '''struct''' Node:&lt;br /&gt;
     '''Node''' son[k]                                 &amp;lt;font color=green&amp;gt;// массив сыновей&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''Node''' go[k]                                  &amp;lt;font color=green&amp;gt;// массив переходов (запоминаем переходы в ленивой рекурсии), используемый для вычисления суффиксных ссылок&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''Node''' parent                                 &amp;lt;font color=green&amp;gt;// вершина родитель&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''Node''' suffLink                               &amp;lt;font color=green&amp;gt;// суффиксная ссылка (вычисляем в ленивой рекурсии)&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''Node''' up                                     &amp;lt;font color=green&amp;gt;// сжатая суффиксная ссылка&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''char''' charToParent                           &amp;lt;font color=green&amp;gt;// символ, ведущий к родителю&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''bool''' isLeaf                                 &amp;lt;font color=green&amp;gt;// флаг, является ли вершина терминалом&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''vector&amp;lt;int&amp;gt;''' leafPatternNumber               &amp;lt;font color=green&amp;gt;// номера строк, за которые отвечает терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Функция для вычисления суффиксной ссылки:'''&lt;br /&gt;
 '''Node''' getSuffLink('''Node''' v):&lt;br /&gt;
     '''if''' v.suffLink == ''null''                       &amp;lt;font color=green&amp;gt;// если суффиксная ссылка ещё не вычислена&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' v == root '''or''' v.parent == root&lt;br /&gt;
             v.suffLink = root&lt;br /&gt;
        '''else'''&lt;br /&gt;
             v.suffLink = getLink(getSuffLink(v.parent), v.charToParent)&lt;br /&gt;
     '''return''' v.suffLink&lt;br /&gt;
 &lt;br /&gt;
'''Функция для вычисления перехода:'''&lt;br /&gt;
 '''Node''' getLink('''Node''' v, '''char''' c): &lt;br /&gt;
    '''if''' v.go[c] == ''null''                           &amp;lt;font color=green&amp;gt;// если переход по символу c ещё не вычислен&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' v.son[c]&lt;br /&gt;
             v.go[c] = v.son[c]&lt;br /&gt;
         '''else''' '''if''' v == root &lt;br /&gt;
             v.go[c] = root &lt;br /&gt;
         '''else''' &lt;br /&gt;
             v.go[c] = getLink(getSuffLink(v), c)&lt;br /&gt;
     '''return''' v.go[c]&lt;br /&gt;
 &lt;br /&gt;
'''Функция для вычисления сжатой суффиксной ссылки:'''&lt;br /&gt;
 '''Node''' getUp('''Node''' v):&lt;br /&gt;
     '''if''' v.up == ''null''                             &amp;lt;font color=green&amp;gt;// если сжатая суффиксная ссылка ещё не вычислена&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''if''' getSuffLink(v).isLeaf&lt;br /&gt;
             v.up = getSuffLink(v)&lt;br /&gt;
         '''else''' '''if''' getSuffLink(v) == root&lt;br /&gt;
             v.up = root&lt;br /&gt;
         '''else''' &lt;br /&gt;
             v.up = getUp(getSuffLink(v))&lt;br /&gt;
     '''return''' v.up&lt;br /&gt;
&lt;br /&gt;
'''Функция для добавления строки в бор:'''&lt;br /&gt;
 '''fun''' addString('''string''' s, '''int''' patternNumber):&lt;br /&gt;
     '''Node''' cur = root&lt;br /&gt;
     '''for''' i = 0 '''to''' s.length - 1&lt;br /&gt;
         '''char''' c = s[i]&lt;br /&gt;
         '''if''' cur.son[c] == 0&lt;br /&gt;
             cur.son[c] = Node&lt;br /&gt;
             &amp;lt;font color=green&amp;gt;/* здесь также нужно обнулить указатели на переходы и сыновей */&amp;lt;/font&amp;gt;&lt;br /&gt;
             cur.son[c].suffLink = 0&lt;br /&gt;
             cur.son[c].up = 0&lt;br /&gt;
             cur.son[c].parent = cur&lt;br /&gt;
             cur.son[c].charToParent = c&lt;br /&gt;
             cur.son[c].isLeaf = ''false''&lt;br /&gt;
         cur = cur.son[c]&lt;br /&gt;
     cur.isLeaf = ''true''&lt;br /&gt;
     cur.leafPatternNumber.pushBack(patternNumber)&lt;br /&gt;
'''Функция для процессинга текста (поиск, встречается строка или нет):'''&lt;br /&gt;
 '''fun''' processText('''string''' t):   &lt;br /&gt;
     '''Node''' cur = root&lt;br /&gt;
     '''for''' i = 0 '''to''' t.length - 1 &lt;br /&gt;
         '''char''' c = t[i] - 'a'&lt;br /&gt;
         cur = getLink(cur, c)&lt;br /&gt;
         &amp;lt;font color=green&amp;gt;/* В этом месте кода должен выполняться переход по '''сжатой''' суффиксной ссылке getUp(cur). Для вершины,&lt;br /&gt;
            обнаруженной по ней тоже ставим, что она найдена, затем повторяем для её сжатой суффиксной ссылки&lt;br /&gt;
            и так до корня. */&amp;lt;/font&amp;gt;&lt;br /&gt;
Кроме этих функций требуется инициализация, но она имеет отношение только к кодированию, поэтому здесь приведена не будет.&lt;br /&gt;
&lt;br /&gt;
== Оптимизации ==&lt;br /&gt;
Существует несколько оптимизаций данного алгоритма, направленных на случаи, когда нас интересует только первое вхождение образца в текст:&lt;br /&gt;
&lt;br /&gt;
# '''Сброс сжатых суффиксных ссылок для посещённых вершин.''' &lt;br /&gt;
#: Существенно ускорить работу алгоритма могут пометки о посещённости узла, то есть если узел посещён, то не переходить по сжатым суффиксным ссылкам. Вместо хранения пометок можно просто сбрасывать сжатую суффиксную ссылку.&lt;br /&gt;
# '''Сброс пометки терминальной вершины.''' &lt;br /&gt;
#: В изначальном множестве образцов могут быть дублирующиеся строки. Мы можем хотеть из различать, если с одинаковыми строками связана разная мета-информация. Тогда при попадании в терминальную вершину можно осуществлять сброс пометки этой терминальной вершины, что сэкономит время на обновлении информации о вхождении образцов в текст. Тривиальным примером, в котором возникает ситуация долгой обработки, служит огромное множество образцов из одинаковых символов и текст только из этих символов.&lt;br /&gt;
&lt;br /&gt;
== Поиск шаблонов с масками ==&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Пусть &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; {{---}} маска, обозначающая любой одиночный символ. Необходимо найти для каждого заданного шаблона с масками все его вхождения в текст.&amp;lt;BR&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Например, шаблон &amp;lt;tex&amp;gt;ab\varphi\varphi c\varphi&amp;lt;/tex&amp;gt;, который содержит в себе три маски, встречается на позициях &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;xabvccababcax&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Алгоритм поиска ===&lt;br /&gt;
&lt;br /&gt;
Для того чтобы найти все вхождения в текст заданного шаблона с масками &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, необходимо обнаружить вхождения в текст всех его безмасочных кусков.&amp;lt;BR&amp;gt;&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\{Q_1, \dots, Q_k \}&amp;lt;/tex&amp;gt; {{---}} набор подстрок&lt;br /&gt;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;, разделенных масками, и пусть &amp;lt;tex&amp;gt;\{ l_1, \dots, l_k \}&amp;lt;/tex&amp;gt; {{---}} их стартовые позиции в &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;. Например, шаблон &amp;lt;tex&amp;gt;ab\varphi\varphi c\varphi&amp;lt;/tex&amp;gt; содержит две подстроки без масок &amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; и их стартовые позиции соответственно &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;. Для алгоритма понадобится массив &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;C[i]&amp;lt;/tex&amp;gt; {{---}} количество встретившихся в тексте безмасочных подстрок шаблона, который начинается в тексте на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Тогда появление подстроки &amp;lt;tex&amp;gt;Q_i&amp;lt;/tex&amp;gt; в тексте на позиции &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; будет означать возможное появление шаблона на позиции &amp;lt;tex&amp;gt;j - l_i + 1&amp;lt;/tex&amp;gt;.&amp;lt;BR&amp;gt;&lt;br /&gt;
# Используя алгоритм Ахо-Корасик, находим безмасочные подстроки шаблона &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;: когда находим &amp;lt;tex&amp;gt;Q_i&amp;lt;/tex&amp;gt; в тексте &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на позиции &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, увеличиваем на единицу &amp;lt;tex&amp;gt;C[j - l_i + 1]&amp;lt;/tex&amp;gt;.&amp;lt;BR&amp;gt;&lt;br /&gt;
# Каждое &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, для которого &amp;lt;tex&amp;gt;C[i] = k&amp;lt;/tex&amp;gt;, является стартовой позицией появления шаблона &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; в тексте.&amp;lt;BR&amp;gt;&lt;br /&gt;
Рассмотрим подстроку текста &amp;lt;tex&amp;gt;T[i \dots i+n-1]&amp;lt;/tex&amp;gt;. Равенство &amp;lt;tex&amp;gt;C[i] = k&amp;lt;/tex&amp;gt; будет означать, что подстроки текста &amp;lt;tex&amp;gt; T[i + l_1 \dots i + l_1 + |Q_1| - 1],  T[i + l_2 \dots i + l_2 + |Q_2| - 1]&amp;lt;/tex&amp;gt; и так далее будут равны соответственно безмасочным подстрокам шаблона &amp;lt;tex&amp;gt;\{Q_1, \dots , Q_k \}&amp;lt;/tex&amp;gt;. Остальная часть шаблона является масками, поэтому шаблон входит в текст на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&amp;lt;BR&amp;gt;&lt;br /&gt;
Поиск подстрок заданного шаблона с помощью алгоритма Ахо-Корасик выполняется за время &amp;lt;tex&amp;gt;O(m+n+a)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} суммарная длина подстрок, то есть длина шаблона, &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; {{---}} длина текста, &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} количество появлений подстрок шаблона. Далее просто надо пробежаться по массиву &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; и просмотреть значения ячеек за время &amp;lt;tex&amp;gt;O (m)&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;
*[http://e-maxx.ru/algo/aho_corasick MAXimal :: algo :: Алгоритм Ахо-Корасик]&lt;br /&gt;
*[http://aho-corasick.narod.ru Сопоставление множеств и алгоритм Ахо-Корасик]&lt;br /&gt;
*[http://codeforces.com/blog/entry/14854?locale=ru Codeforces :: Алгоритм Ахо-Корасик]&lt;br /&gt;
*[https://habrahabr.ru/post/198682/ Habr :: Алгоритм Ахо-Корасик]&lt;br /&gt;
*[https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%90%D1%85%D0%BE_%E2%80%94_%D0%9A%D0%BE%D1%80%D0%B0%D1%81%D0%B8%D0%BA Wiki :: Алгоритм Ахо-Корасик]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]] &lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;br /&gt;
[[Категория: Точный поиск]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Z-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=62180</id>
		<title>Z-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Z-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=62180"/>
				<updated>2017-11-15T20:14:49Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Z-функция''' (англ. ''Z-function'') от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и позиции &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; — это длина максимального префикса подстроки, начинающейся с позиции &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, который одновременно является и префиксом всей строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Более формально, &amp;lt;tex&amp;gt;Z[i](s) = \max k \mid s[i\, \ldots \, i + k] = s[0 \ldots k]&amp;lt;/tex&amp;gt;. &amp;lt;!-- проинлайнил \twodots из clrscode --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Значение Z-функции от первой позиции не определено, поэтому его обычно приравнивают к нулю или к длине строки.&lt;br /&gt;
}}&lt;br /&gt;
'''Примечание:''' далее в конспекте символы строки нумеруются с нуля.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Zfunc-examp.png|мини|500px|Строка и её Z-функция]]&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;n&amp;lt;/tex&amp;gt; — длина строки. Для каждой позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; перебираем для неё ответ, начиная с нуля, пока не обнаружим несовпадение или не дойдем до конца строки. &lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
  '''int'''[] zFunction(s : '''string'''):&lt;br /&gt;
    '''int'''[] zf = '''int'''[n]&lt;br /&gt;
    '''for''' i = 1 '''to''' n − 1&lt;br /&gt;
      '''while''' i + zf[i] &amp;lt; n '''and''' s[zf[i]] == s[i + zf[i]]&lt;br /&gt;
        zf[i]++&lt;br /&gt;
    '''return''' zf&lt;br /&gt;
&lt;br /&gt;
== Эффективный алгоритм поиска ==&lt;br /&gt;
&lt;br /&gt;
Z-блоком назовем подстроку с началом в позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и длиной &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Для работы алгоритма заведём две переменные: &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; — начало и конец Z-блока строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; с максимальной позицией конца &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; (среди всех таких Z-блоков, если их несколько, выбирается наибольший). Изначально &amp;lt;tex&amp;gt;left=0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть нам известны значения Z-функции от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt;. Найдём &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt;. &lt;br /&gt;
Рассмотрим два случая.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;i &amp;gt; right&amp;lt;/tex&amp;gt;:&amp;lt;br&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;Просто пробегаемся по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и сравниваем символы на позициях &amp;lt;tex&amp;gt;S[i+j]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S[j]&amp;lt;/tex&amp;gt;.&amp;lt;!--&lt;br /&gt;
--&amp;gt;Пусть &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; первая позиция в строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; для которой не выполняется равенство &amp;lt;tex&amp;gt;S[i+j] = S[j]&amp;lt;/tex&amp;gt;, тогда &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; это и Z-функция для позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;left = i, right = i + j - 1&amp;lt;/tex&amp;gt;. В данном случае будет определено корректное значение &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt; в силу того, что оно определяется наивно, путем сравнения с начальными символами строки.&lt;br /&gt;
# &amp;lt;tex&amp;gt;i \leqslant right&amp;lt;/tex&amp;gt;:&amp;lt;br&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;Сравним &amp;lt;tex&amp;gt;Z[i - left] + i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; меньше, то надо просто наивно пробежаться по строке начиная с позиции &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; и вычислить значение &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt;. Корректность в таком случае также гарантирована.&amp;lt;!--&lt;br /&gt;
--&amp;gt;Иначе мы уже знаем верное значение &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt;, так как оно равно значению &amp;lt;tex&amp;gt;Z[i - left]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
[[Файл:z-func.png]]&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Этот алгоритм работает за &amp;lt;tex&amp;gt;O(|S|)&amp;lt;/tex&amp;gt;, так как каждая позиция пробегается не более двух раз: при попадании в диапазон от &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; и при высчитывании Z-функции простым циклом.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
  '''int'''[] zFunction(s : '''string'''):&lt;br /&gt;
    '''int'''[] zf = '''int'''[n]&lt;br /&gt;
    '''int''' left = 0, right = 0&lt;br /&gt;
    '''for''' i = 1 '''to''' n − 1&lt;br /&gt;
      zf[i] = max(0, min(right − i, zf[i − left]))&lt;br /&gt;
      '''while''' i + zf[i] &amp;lt; n '''and''' s[zf[i]] == s[i + zf[i]]&lt;br /&gt;
        zf[i]++&lt;br /&gt;
      '''if''' i + zf[i] &amp;gt; right&lt;br /&gt;
        left = i&lt;br /&gt;
        right = i + zf[i]&lt;br /&gt;
    '''return''' zf&lt;br /&gt;
&lt;br /&gt;
== Поиск подстроки в строке с помощью Z-функции ==&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; — длина текста. &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; — длина образца. &amp;lt;br&amp;gt; &lt;br /&gt;
Образуем строку &amp;lt;tt&amp;gt;s = pattern + # + text&amp;lt;/tt&amp;gt;, где &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; — символ, не встречающийся ни в &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, ни в &amp;lt;tt&amp;gt;pattern&amp;lt;/tt&amp;gt;. Вычисляем Z-функцию от этой строки.&lt;br /&gt;
В полученном массиве, в позициях в которых значение Z-функции равно &amp;lt;tex&amp;gt;|\texttt{pattern}|&amp;lt;/tex&amp;gt;, по определению начинается подстрока, совпадающая с &amp;lt;tt&amp;gt;pattern&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
  '''int''' substringSearch(text : '''string''', pattern : '''string'''):&lt;br /&gt;
    '''int'''[] zf = zFunction(pattern + '#' + text)&lt;br /&gt;
    '''for''' i = m + 1 '''to''' n + 1&lt;br /&gt;
      '''if''' zf[i] == m &lt;br /&gt;
        '''return''' i&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Построение строки по Z-функции==&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition= Необходимо восстановить строку по Z-функции, считая алфавит ограниченным.&lt;br /&gt;
}}&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
Пусть в массиве &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt; хранятся значения Z-функции, в &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Нужно узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;z[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;z[i] = 0&amp;lt;/tex&amp;gt;, тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем ещё не использованный символ или последний использованный символ алфавита, если мы уже использовали все символы. Если &amp;lt;tex&amp;gt;z[i] \neq 0&amp;lt;/tex&amp;gt;, то нам нужно записать префикс длины &amp;lt;tex&amp;gt;z[i]&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Но если при посимвольном записывании этого префикса в конец строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; мы нашли такой &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; (индекс последнего символа строки), что &amp;lt;tex&amp;gt;z[j]&amp;lt;/tex&amp;gt; больше, чем длина оставшейся незаписанной части префикса, то мы перестаём писать этот префикс и пишем префикс длиной &amp;lt;tex&amp;gt;z[j]&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для правильной работы алгоритма будем считать значение &amp;lt;tex&amp;gt;z[0]&amp;lt;/tex&amp;gt; равным нулю.&lt;br /&gt;
&lt;br /&gt;
Заметим, что не всегда удастся восстановить строку с ограниченным алфавитом неподходящего размера. Например, для строки &amp;lt;tex&amp;gt;abacaba&amp;lt;/tex&amp;gt; массив Z-функций будет &amp;lt;tex&amp;gt;[0, 0, 1, 0, 3, 0, 1]&amp;lt;/tex&amp;gt;. Используя двоичный алфавит, мы получим строку &amp;lt;tex&amp;gt;abababa&amp;lt;/tex&amp;gt;, но её массив Z-функций отличается от исходного. Ошибка восстановления строки возникла, когда закончились новые символы алфавита.&lt;br /&gt;
&lt;br /&gt;
Если строить строку по некорректному массиву значений Z-функции, то мы получим какую-то строку, но массив значений Z-функций от неё будет отличаться от исходного.&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Этот алгоритм работает за O(|S|), так как мы один раз проходим по массиву Z-функций.&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromZ(z : '''int'''[], alphabet : '''char'''[]):&lt;br /&gt;
   '''string''' s = &amp;quot;&amp;quot;&lt;br /&gt;
   '''int''' prefixLength = 0 &amp;lt;font color=green&amp;gt;// длина префикса, который мы записываем&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''int''' j &amp;lt;font color=green&amp;gt;// позиция символа в строке, который будем записывать&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''int''' newCharacter = 0 &amp;lt;font color=green&amp;gt;// индекс нового символа&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''for''' i = 0 '''to''' z.length - 1&lt;br /&gt;
       &amp;lt;font color=green&amp;gt;// мы не пишем какой-то префикс и не будем писать новый&amp;lt;/font&amp;gt;&lt;br /&gt;
       '''if''' z[i] = 0 '''and''' prefixLength = 0&lt;br /&gt;
           if newCharacter &amp;lt; alphabet.length&lt;br /&gt;
               s += alphabet[newCharacter]&lt;br /&gt;
               newCharacter++&lt;br /&gt;
           else&lt;br /&gt;
               s += alphabet[newCharacter - 1]&lt;br /&gt;
       &amp;lt;font color=green&amp;gt;// нам нужно запомнить, что мы пишем префикс &amp;lt;/font&amp;gt;&lt;br /&gt;
       '''if''' z[i] &amp;gt; prefixLength&lt;br /&gt;
           prefixLength = z[i]&lt;br /&gt;
           j = 0&lt;br /&gt;
       &amp;lt;font color=green&amp;gt;// пишем префикс&amp;lt;/font&amp;gt;&lt;br /&gt;
       '''if''' prefixLength &amp;gt; 0&lt;br /&gt;
           s += s[j]&lt;br /&gt;
           j++&lt;br /&gt;
           prefixLength--       &lt;br /&gt;
   '''return''' s&lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности алгоритма===&lt;br /&gt;
&lt;br /&gt;
Докажем, что если нам дали корректную Z-функцию, то наш алгоритм построит строку с такой же Z-функцией.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt; — данная Z-функция, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; — массив значений Z-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Покажем, что массивы &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt; будут совпадать.&lt;br /&gt;
&lt;br /&gt;
[[Файл: Запись_префикса.png|330px|thumb|right|Записали префикс, начинающийся в &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. После пишем префикс, начинающийся в &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;. Этот префикс не изменит символы первого префикса.]]&lt;br /&gt;
&lt;br /&gt;
Рассмотрим похожий алгоритм, но с более худшей асимптотикой. Отличие будет в том, что при &amp;lt;tex&amp;gt;z[i] &amp;gt; 0&amp;lt;/tex&amp;gt; мы будем писать префикс полностью и возвращаться в позицию &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt;. Рассмотрим каждый шаг этого алгоритма. Если &amp;lt;tex&amp;gt;z[i] = 0&amp;lt;/tex&amp;gt;, то мы пишем символ, отличный от первого символа строки, поэтому &amp;lt;tex&amp;gt;q[i] = 0&amp;lt;/tex&amp;gt;, а значит &amp;lt;tex&amp;gt;q[i] = z[i]&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;z[i] &amp;gt; 0&amp;lt;/tex&amp;gt;, то при записи &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; мы будем получать &amp;lt;tex&amp;gt;q[i] = z[i]&amp;lt;/tex&amp;gt;, потому что мы переписали префикс строки. Но далее мы можем переписать этот префикс другим префиксом. Заметим, что новый префикс будет содержаться и в префиксе самой строки, поэтому пересечение двух префиксов будет состоять из одинаковых символов. Значит, префикс не будет изменяться, как и значение &amp;lt;tex&amp;gt;q[i]&amp;lt;/tex&amp;gt;. Тогда массив &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; совпадает с &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Покажем, что этот алгоритм эквивалентен нашему алгоритму. Когда мы пишем разные префиксы, то возможны три варианта: они не пересекаются (начало и конец одного префикса не принадлежат другому), один лежит внутри другого (начало и конец префикса принадлежит другому), они пересекаются (начало одного префикса пренадлежит другому, но конец не принадлежит).&lt;br /&gt;
* Если префиксы не пересекаются, то в алгоритме они не влияют друг на друга.&lt;br /&gt;
[[Файл: Префиксы1.png|400px]]&lt;br /&gt;
* Если префикс лежит внутри другого префикса, то записав большой префикс мы запишем и малый, поэтому не нужно возвращаться к началу малого префикса.&lt;br /&gt;
[[Файл: Префиксы2.png|400px]]&lt;br /&gt;
* Если префиксы пересекаются, то нам нужно переписать часть префикса, который начинается раньше, и начать писать другой префикс (начало этого префикса запишет конец префикса, начинающегося раньше). Если полностью переписать префикс, начинающийся раньше, то мы не сможем восстановить префикс, который начинался раньше конца первого префикса.&lt;br /&gt;
[[Файл: Префиксы3.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, алгоритмы эквивалентны и наш алгоритм тоже корректен.&lt;br /&gt;
&lt;br /&gt;
==Построение Z-функции по префикс-функции== &lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=  Дан массив с корректной [[Префикс-функция | префикс-функцией]] для строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Требуется получить массив с Z-функцией для строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}[[Файл:Case one.png|300px|thumb|right|'''Случай первый''']]&lt;br /&gt;
[[Файл:Case two.png|300px|thumb|right|'''Случай второй''']]&lt;br /&gt;
[[Файл:Case three.png|300px|thumb|right|'''Случай третий''']]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Описание алгоритма=== &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Пусть префикс функция хранится в массиве &amp;lt;tex&amp;gt;P[0 \ldots n - 1]&amp;lt;/tex&amp;gt;. Z-функцию будем записывать в массив &amp;lt;tex&amp;gt;Z[0 \ldots n-1]&amp;lt;/tex&amp;gt;. Заметим, что если &amp;lt;tex&amp;gt;P[i]&amp;gt;0&amp;lt;/tex&amp;gt;, то мы можем заявить, что &amp;lt;tex&amp;gt;Z[i-P[i]+1]&amp;lt;/tex&amp;gt; будет не меньше, чем &amp;lt;tex&amp;gt;P[i]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Так же заметим, что после такого прохода в &amp;lt;tex&amp;gt;Z[1]&amp;lt;/tex&amp;gt; будет максимальное возможное значение. Далее будем поддерживать инвариант: в &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt; будет максимальное возможное значение.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Пусть в &amp;lt;tex&amp;gt;Z[i] = z &amp;gt; 0&amp;lt;/tex&amp;gt;, рассмотрю &amp;lt;tex&amp;gt;j&amp;lt;z&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;Z[j]=k&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;Z[i+j]=k_1&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;b_1=s[0 \ldots k-1]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b_2=s[j \ldots j+k-1]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b_3=s[0 \ldots z-1]&amp;lt;/tex&amp;gt;. Тогда заметим, что &amp;lt;tex&amp;gt;b_3 = s[i \ldots i+z-1]&amp;lt;/tex&amp;gt; и тогда возможны три случая:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;k&amp;lt;k_1&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#: Тогда &amp;lt;tex&amp;gt;b_1 \subset s[0 \ldots k_1-1]=s[i+j \ldots i+j+k_1-1]&amp;lt;/tex&amp;gt; и тогда очевидно, что мы не можем увеличить значение &amp;lt;tex&amp;gt;Z[i+j]&amp;lt;/tex&amp;gt; и надо рассматривать уже &amp;lt;tex&amp;gt;i=i+j&amp;lt;/tex&amp;gt;. &lt;br /&gt;
# &amp;lt;tex&amp;gt;k&amp;lt;z-j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;gt;k_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#: Тогда &amp;lt;tex&amp;gt;b_1 = b_2 \subset b_3 = s[i \ldots i+z-1] \Rightarrow b_1 = s[i+j \ldots i+j+k-1]&amp;lt;/tex&amp;gt; и тогда очевидно, что &amp;lt;tex&amp;gt;Z[i+j]&amp;lt;/tex&amp;gt; можно увеличить до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. &lt;br /&gt;
# &amp;lt;tex&amp;gt;k&amp;gt;z-j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k&amp;gt;k_1&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#: Тогда &amp;lt;tex&amp;gt;b_1 = b_2 &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt;b_2&amp;lt;/tex&amp;gt; не является подстрокой строки &amp;lt;tex&amp;gt;b_3&amp;lt;/tex&amp;gt; (так как&amp;lt;tex&amp;gt;j+k-1 &amp;gt; z&amp;lt;/tex&amp;gt;). Так как известно, что &amp;lt;tex&amp;gt;s[z] \ne s[i+z]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;s[0 \ldots z-j] = s[i+j \ldots i+z-1]&amp;lt;/tex&amp;gt; и тогда понятно, что &amp;lt;tex&amp;gt;Z[i+j]=z-j&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''int[]''' buildZFunctionFromPrefixFunction(P : '''int'''[n])&lt;br /&gt;
   '''int'''[] Z = '''int'''[n]&lt;br /&gt;
   '''for''' i = 1 '''to''' n - 1&lt;br /&gt;
      '''if''' P[i] &amp;gt; 0&lt;br /&gt;
         Z[i - P[i] + 1] = P[i]&lt;br /&gt;
   Z[0] = n&lt;br /&gt;
   '''int''' i = 1&lt;br /&gt;
   '''while''' i &amp;lt; n &lt;br /&gt;
      '''int''' t = i&lt;br /&gt;
      '''if''' Z[i] &amp;gt; 0&lt;br /&gt;
         '''for''' j = 1 '''to''' Z[i] - 1&lt;br /&gt;
            '''if''' Z[i + j] &amp;gt; Z[j]&lt;br /&gt;
               '''break'''&lt;br /&gt;
            Z[i + j] = min(Z[j], Z[i] - j)&lt;br /&gt;
            t = i + j&lt;br /&gt;
      i = t + 1&lt;br /&gt;
   '''return''' Z&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Внешний цикл &amp;lt;tex&amp;gt;\mathrm{while}&amp;lt;/tex&amp;gt; отработает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; итераций, так как внутри него &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; увеличивается не менее чем на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. А внутренний цикл выполнит суммарно не более &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; итераций, так как после него &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; увеличится на количество итераций внутреннего цикла, но &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; не может увеличиться более чем на &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, так как каждое значение &amp;lt;tex&amp;gt;Z[i]&amp;lt;/tex&amp;gt; не может превзойти &amp;lt;tex&amp;gt;n&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;
* [http://habrahabr.ru/post/113266/ Поиск подстроки и смежные вопросы — Хабр]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[wikipedia:ru:Z-функция | Википедия — Z-функция]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [http://codeforces.ru/blog/entry/9612/ Codeforces — Переход между Z- и префикс- функциями]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;br /&gt;
[[Категория:Точный поиск]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%BD%D1%8B%D0%B5_%D1%82%D1%80%D0%B0%D0%BD%D1%81%D0%BB%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&amp;diff=62116</id>
		<title>Атрибутные транслирующие грамматики</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%BD%D1%8B%D0%B5_%D1%82%D1%80%D0%B0%D0%BD%D1%81%D0%BB%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&amp;diff=62116"/>
				<updated>2017-10-27T03:51:47Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Атрибуты в ANTLR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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;wikitex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Синтаксически управляемое определение''' ''(англ. syntax-directed definition)'' является [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|контекстно-свободной]] грамматикой с атрибутами и правилами. Атрибуты связаны с грамматическими символами, а правила — с продукциями. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Синтаксически управляемая трансляция''' ''(англ. syntax-directed translation)'' {{---}} это трансляция, при которой в [[Предиктивный_синтаксический_анализ| процессе разбора]] строки сразу выполняются какие-то действия, без использования промежуточного представления в виде дерева разбора.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Синтаксически управляемая трансляция вводит две новые сущности: '''атрибут''' и '''транслирующий символ'''.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибут''' ''(англ. attribute)'' {{---}} дополнительные данные, ассоциированные с грамматическими символами. Если $X$ представляет собой символ, а $a$ — один из его атрибутов, то значение $a$ в некотором узле дерева разбора, помеченном $X$, записывается как $X.a$. Если узлы дерева разбора реализованы в виде записей или объектов, то атрибуты $X$ могут быть реализованы как поля данных в записях, представляющих узлы $X$. Атрибуты могут быть любого вида: числами, типами, таблицами ссылок или строками.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Дерево разбора, в каждом узле которого атрибуты уже вычислены, называется '''аннотированным''' ''(англ. annotated)'', а процесс вычисления этих атрибутов {{---}} '''аннотированием''' дерева разбора.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id = tr_char&lt;br /&gt;
|definition =&lt;br /&gt;
'''Транслирующий символ''' {{---}} нетерминал, который раскрывается в $\varepsilon$ и в момент раскрытия выполняет связанное с ним действие. Действия пишутся в фигурных скобках рядом с транслирующим символом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Будем рассматривать в качестве примера грамматику для арифметических выражений с операторами $+$ и $*$:&lt;br /&gt;
&lt;br /&gt;
$&lt;br /&gt;
S \to E \\ &lt;br /&gt;
E \to E + T \mid T \\&lt;br /&gt;
T \to T * F \mid F \\&lt;br /&gt;
F \to n \mid (E) &lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что не существует гарантии наличия даже одного порядка обхода дерева разбора, при котором вычислятся все атрибуты в узлах. Рассмотрим для примера следующие нетерминалы $A$ и $B$:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Продукция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Семантические правила&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $A \to B$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $A.s = B.i \\ B.i = A.s+1$&lt;br /&gt;
|}&lt;br /&gt;
Данные правила циклические: невозможно вычислить ни $A.s$ в узле, ни $B.i$ в дочернем узле, не зная значение другого атрибута. &lt;br /&gt;
Далее будет рассмотрено два класса синтаксически управляемых грамматик, для которых можно однозначно определить порядок вычисления атрибутов.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Синтезируемые атрибуты==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибут''', значение которого зависит от значений атрибутов детей данного узла или от других атрибутов этого узла, то атрибут называется '''синтезируемым''' ''(англ. synthesized attribute)''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Грамматика называется '''S-атрибутной''' ''(англ. S-attributed definition)'', если с атрибутами выполняются только операции присваивания значений других атрибутов, а внутри транслирующих символов происходят обращения только к атрибутам этого транслирующего символа. То есть в грамматике используются только синтезируемые атрибуты. Дерево разбора для такой грамматике всегда может быть аннотировано путем выполнения семантических правил снизу вверх, от листьев к корню.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
===Пример S-атрибутной грамматики===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Выпишем синтаксически управляемое определение для грамматики арифметических выражений с операторами $+$ и $*$ (здесь $\{ADD {{...}} \}$ и $\{MUL {{...}} \}$ {{---}} [[Атрибутные_транслирующие_грамматики#tr_char|транслирующие символы]]. Если в продукции несколько раз встречается одинаковый нетерминал, будем добавлять к нему индексы, считая от начала продукции.):&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Продукция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Семантические правила&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Пояснения&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $S \to E$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $S.val=E.val$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $E_0 \to E_1 + T\ \{ADD\  res = op_1 + op_2\}$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $ADD.op_1=E_1.val \\ ADD.op_2=T.val \\ E_0.val=ADD.res $&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| В фигурных скобках {{---}} действия транслирующего символа ADD. $op_1$, $op_2$ и $res$ {{---}} атрибуты транслирующего символа. &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $E \to T$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $E.val=T.val$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T_0 \to T_1 * F \ \{MUL\  res = op_1 \times op_2\}$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $MUL.op_1=T.val \\ MUL.op_2=F.val \\ T_0.val=MUL.res$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| В фигурных скобках {{---}} действия транслирующего символа MUL. $op_1$, $op_2$ и $res$ {{---}} атрибуты транслирующего символа. &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T \to F$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T.val=F.val$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $F \to n$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $F.val=n.val$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $F \to (E)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $F.val=E.val$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В нашем примере видно, что $val$ зависит только от детей в дереве разбора, то есть это синтезируемый атрибут. Результат умножителя ($MUL.res$) зависит только от атрибутов атрибутов самого умножителя ($MUL.op_1$ и $MUL.op_2$), а значит тоже является синтезируемым(аналогично с сумматором $ADD$). &lt;br /&gt;
&lt;br /&gt;
[[Файл:3mul5add4.png|500px|thumb|center|Аннотированное дерево разбора для '''$3*5+4$''']]&lt;br /&gt;
&lt;br /&gt;
После такого разбора в $S.val$ будет лежать вычисленное значение выражения. Можно, например сразу напечатать его, добавив к нему правило $\{print(S.val)\}$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Наследуемые атрибуты==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибут''', значение которого зависит от значений атрибутов братьев узла или атрибутов родителя, называется '''наследуемым''' ''(англ. inherited attribute)''. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Грамматика называется '''L-атрибутной''' ''(англ. L-attributed definition)'', если значения наследуемых атрибутов зависят только от родителей и братьев слева (то есть не зависят от значений атрибутов братьев справа).&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
===Пример L-атрибутной грамматики===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Для наглядности рассмотрим грамматику объявления переменных &lt;br /&gt;
(в начале строки идет тип, затем через запятую имена переменных. Примеры строк, разбираемых в ней: '''int a''' или '''real x,y,z''' и подобные):&lt;br /&gt;
&lt;br /&gt;
$&lt;br /&gt;
D \to TL \\&lt;br /&gt;
T \to int \mid real \\&lt;br /&gt;
L \to L,id \mid id&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Выпишем продукции (с транслирующими символами) и ассоциируем с ними семантические правила&lt;br /&gt;
(здесь $\{ENTRY {{...}} \}$ {{---}} [[Атрибутные_транслирующие_грамматики#tr_char|транслирующий символ]]. Если в продукции несколько раз встречается одинаковый нетерминал, будем добавлять к нему индексы, считая от начала продукции.):&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Продукция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Семантические правила&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $D \to TL$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $L.inh = T.type$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T \to int$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T.type = integer$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T \to real$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $T.type = real$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $L_0 \to L_1,id\ \{ENTRY addtype(key, value)\}$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $L_1.inh = L0.inh \\ ENTRY.key=id.text \\ ENTRY.value=L_0.inh$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $L \to id\ \{ENTRY addtype(key, value)\}$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| $ENTRY.key=id.text \\ ENTRY.value=L.inh$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Семантическое правило  $L.inh = T.type$, связанное с продукцией $D \to TL$, определяет наследуемый атрибут $L.inh$ как тип объявления. Затем приведенные правила распространяют этот тип вниз по дереву разбора с использованием атрибута $L.inh$. Транслирующий символ $ENTRY$, связанный с продукциями для $L$, вызывает процедуру $addtype$ для добавления типа каждого идентификатора к его записи в таблице символов (по ключу, определяемому атрибутом $text$).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Real_id1,_id2,_id3.png|600px|center|thumb|Аннотированное дерево разбора для '''$\mathbf{real}\ id1,\ id2,\ id3$'''|600px]]&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Пример работы с атрибутами в нисходящем разборе==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим работы с атрибутами на примере LL(1)-грамматики арифметических выражений, которая уже была разобрана [[Построение FIRST и FOLLOW#Пример | ранее]] и расширим код [[Предиктивный_синтаксический_анализ | разборщика]] для нее:&lt;br /&gt;
&lt;br /&gt;
$&lt;br /&gt;
E \to TE' \\&lt;br /&gt;
E' \to +TE' \mid \varepsilon \\&lt;br /&gt;
T \to FT' \\&lt;br /&gt;
T' \to * FT' \mid \varepsilon \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
В данной реализации рекурсивные функции от нетерминалов получают на вход (если необходимо) наследуемые атрибуты узла и возвращают вершины дерева разбора, в атрибутах которых записан результат вычислений соответствующего подвыражения. Однако этот код легко изменить, чтобы он только вычислял значение выражения и не строил дерево разбора. Как мы видим, $val$ {{---}} синтезируемый атрибут, $acc$ {{---}} наследуемый атрибут, $ADD$ {{---}} транслирующий символ. Синим подсвечены строки, отвечающие за работу с атрибутами.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;tex&amp;gt;\mathtt{Node}&amp;lt;/tex&amp;gt; {{---}} структура следующего вида:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
     children : '''map&amp;lt;String, Node&amp;gt;'''&lt;br /&gt;
     name : '''string'''&lt;br /&gt;
     val : '''int'''                  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// атрибут нетерминала&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''function''' addChild('''Node''')    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// функция, подвешивающая поддерево к данному узлу&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 E() : '''Node'''&lt;br /&gt;
     Node res = Node(&amp;quot;E&amp;quot;)&lt;br /&gt;
     '''switch''' (curToken)&lt;br /&gt;
         '''case''' n, '('  :&lt;br /&gt;
             res.addChild(T())            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// подвешиваем левого сына&amp;lt;/font&amp;gt;&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;temp = res.children[&amp;quot;T&amp;quot;].val&amp;lt;/font&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// атрибут левого сына&amp;lt;/font&amp;gt;&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;Node rightSon = E'(temp)    &amp;lt;/font&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// отдадим атрибут левого сына правому как наследуемый атрибут&amp;lt;/font&amp;gt;&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;res.addChild(rightSon)     &amp;lt;/font&amp;gt;  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// подвешиваем правого сына сына&amp;lt;/font&amp;gt;&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;res.val = res.children[&amp;quot;E'&amp;quot;].val&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         '''default''' :&lt;br /&gt;
             &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;error&amp;lt;/font&amp;gt;(&amp;quot;unexpected char&amp;quot;)&lt;br /&gt;
     '''return''' res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 E'(acc) : '''Node'''&lt;br /&gt;
     Node res = Node(&amp;quot;E'&amp;quot;)&lt;br /&gt;
     '''switch''' (curToken) &lt;br /&gt;
         '''case''' '+' :&lt;br /&gt;
             consume('+')&lt;br /&gt;
             res.addChild(Node(&amp;quot;+&amp;quot;))&lt;br /&gt;
             res.addChild(T())&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;temp = res.children[&amp;quot;T&amp;quot;].val&lt;br /&gt;
             ADD.res = ADD(acc, temp)  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// ADD проведет вычисления из наследуемого атрибута add и атрибута ребенка &amp;quot;T&amp;quot;&amp;lt;/font&amp;gt;&lt;br /&gt;
             res.addChild(E'(ADD.res)) &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// результат вычислений будет передан правому ребенку как наследуемый атрибут&amp;lt;/font&amp;gt;&lt;br /&gt;
             res.val = res.children[&amp;quot;E'&amp;quot;].val&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         '''case''' '$', ')' :&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;res.val = acc&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         '''default''' :&lt;br /&gt;
             &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;error&amp;lt;/font&amp;gt;(&amp;quot;unexpected char&amp;quot;)&lt;br /&gt;
      '''return''' res&lt;br /&gt;
&lt;br /&gt;
 F() : '''Node'''&lt;br /&gt;
     Node res = Node(&amp;quot;F&amp;quot;)&lt;br /&gt;
     '''switch''' (curToken)&lt;br /&gt;
         '''case''' n :&lt;br /&gt;
             consume(n)&lt;br /&gt;
             res.addChild(Node(curToken)) &lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;res.val = n.val&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         '''case''' '(' :&lt;br /&gt;
             consume('(')&lt;br /&gt;
             res.addChild(Node(&amp;quot;(&amp;quot;))&lt;br /&gt;
             res.addChild(E())&lt;br /&gt;
             &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;rev.val = res.children[&amp;quot;E&amp;quot;].val&amp;lt;/font&amp;gt;&lt;br /&gt;
             consume(')')&lt;br /&gt;
             res.addChild(Node(&amp;quot;)&amp;quot;))&lt;br /&gt;
         '''default''' :&lt;br /&gt;
             &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;error&amp;lt;/font&amp;gt;(&amp;quot;unexpected char&amp;quot;)&lt;br /&gt;
     '''return''' res&lt;br /&gt;
&lt;br /&gt;
Функции для $T$ и $T'$ строятся аналогично.&lt;br /&gt;
&lt;br /&gt;
[[Файл:2add3add7.png|600px|center|thumb| Дерево разбора для '''$2\ +\ 3\ +\ 7$''']]&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Атрибуты в ANTLR==&lt;br /&gt;
&lt;br /&gt;
Общедоступный генератор разборщиков ANTLR&amp;lt;ref&amp;gt;[http://www.antlr.org/ ANTLR {{---}} Parser generator]&amp;lt;/ref&amp;gt; поддерживает синтаксически управляемое определение. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим для той же грамматики арифметических выражений с операторами &amp;lt;tex&amp;gt;+,\ *&amp;lt;/tex&amp;gt;, скобками и выводом результата выражениая пример на ANTLR.&lt;br /&gt;
&lt;br /&gt;
 grammar Expression;&lt;br /&gt;
 '''@header''' { package ru.ifmo.ctddev.wiki; } &lt;br /&gt;
&lt;br /&gt;
Естественным образом можно добавлять действия в продукции, где это нужно. Действия выполняются после предыдущего элемента грамматики и до следующего.&lt;br /&gt;
&lt;br /&gt;
Стартовый нетерминал печатает результат:&lt;br /&gt;
 s : expr { System.out.println($expr.value); };&lt;br /&gt;
&lt;br /&gt;
В продукции для нетерминала &amp;lt;code&amp;gt;expr&amp;lt;/code&amp;gt; определяется возвращаемое значение (&amp;lt;code&amp;gt;['''int''' value]&amp;lt;/code&amp;gt;). Обращение к этому атрибуту имеет вид &amp;lt;code&amp;gt;$expr.value&amp;lt;/code&amp;gt;. В фигурных скобках записаны семантические правила.&lt;br /&gt;
&lt;br /&gt;
Разобранные нетерминалы возвращают результат, вычисленный в поддереве(&amp;lt;code&amp;gt;returns [int val]&amp;lt;/code&amp;gt;) как свой синтезируемый атрибут, процесс вычисления которого описан в фигурных скобках &amp;lt;code&amp;gt;{ $val = $exprP.val; }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Наследуемые атрибуты передаются нетерминалу как параметр(&amp;lt;code&amp;gt;exprP[$term.val]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
 expr '''returns''' ['''int''' val]&lt;br /&gt;
     : term exprP[$term.val]     { $val = $exprP.val; }&lt;br /&gt;
     ;&lt;br /&gt;
&lt;br /&gt;
 exprP['''int''' i] '''returns''' ['''int''' val]&lt;br /&gt;
     :                                              { $val = $i; } &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-правило&amp;lt;/font&amp;gt;&lt;br /&gt;
     | '+' term expr = exprP[$i + $term.val]        { $val = $expr.val; }&lt;br /&gt;
     ;&lt;br /&gt;
	&lt;br /&gt;
 term '''returns''' ['''int''' val]&lt;br /&gt;
     : fact termP[$fact.val]     { $val = $termpP.val; }&lt;br /&gt;
     ;&lt;br /&gt;
&lt;br /&gt;
 termP['''int''' i] '''returns''' '''[int''' val]&lt;br /&gt;
     :                                              { $val = $i; }&lt;br /&gt;
     | '*' fact expr = termP[$i * $fact.val]        { $val = $expr.val; }&lt;br /&gt;
     ;&lt;br /&gt;
&lt;br /&gt;
 fact '''returns''' ['''int''' val]&lt;br /&gt;
     : '(' expr ')'                  { $val = $expr.val; }&lt;br /&gt;
     | NUM                           { $val = Integer.parseInt($NUM.text); }&lt;br /&gt;
     ;&lt;br /&gt;
&lt;br /&gt;
Техническая деталь для ANTLR, правила для лексического анализатора:&lt;br /&gt;
 WS : [ \t \r \n]+ -&amp;gt; skip ;&lt;br /&gt;
 NUM : [0-9]+ ;&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс. Первое издание. 2003. Стр. 279 {{---}} 305.&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс. Второе издание. 2008. Стр. 383 {{---}} 398.&lt;br /&gt;
* [https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Parser+Rules#ParserRules ANTLR Documentation {{---}} Rule Attribute Definitions]&lt;br /&gt;
* [http://www.amazon.com/The-Definitive-ANTLR-4-Reference/dp/1934356999| The Definitive ANTLR 4 Reference]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Нисходящий разбор]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D0%94%D0%9C_2%D0%BA_2017_%D0%BE%D1%81%D0%B5%D0%BD%D1%8C&amp;diff=62114</id>
		<title>Список заданий по ДМ 2к 2017 осень</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D0%94%D0%9C_2%D0%BA_2017_%D0%BE%D1%81%D0%B5%D0%BD%D1%8C&amp;diff=62114"/>
				<updated>2017-10-26T19:50:20Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
# Постройте граф с $n$ вершинами и $m$ ребрами. Здесь и далее &amp;quot;постройте граф с $n$ вершинами, ...&amp;quot; означает, что вы должны рассказать способ для любого $n$ построить искомый граф, либо рассказать, для каких $n$ такой граф существует и указать способ его построить, а для остальных $n$ доказать, что такого графа не существует. Аналогично следует поступить с другими параметрами, указанными в условии задачи.&lt;br /&gt;
# Обозначим как $N(u)$ множество соседей вершины $u$. Постройте граф с $n$ вершинами, в котором множества $N(u)$ совпадают для всех вершин $u$. &lt;br /&gt;
# Обозначим как $N[u]$ множество, содержащее вершину $u$, а также соседей вершины $u$. Постройте граф с $n$ вершинами, в котором множества $N[u]$ совпадают для всех вершин $u$.&lt;br /&gt;
# Постройте граф с $n$ вершинами, где каждая вершина имеет степень $d$.&lt;br /&gt;
# Докажите, что любой граф, содержащий хотя бы две вершины, имеет две вершины одинаковой степени.&lt;br /&gt;
# Обозначим как $\delta(G)$ минимальную степень вершины в графе, как $\Delta(G)$ - максимальную степень вершины в графе. Постройте граф с $n$ вершинами, в котором $\delta(G) + \Delta(G) &amp;gt; n$.&lt;br /&gt;
# Постройте двудольный граф с $n$ вершинами, в котором $\delta(G) + \Delta(G) &amp;gt; n$.&lt;br /&gt;
# Пусть для двудольного графа выполнено условие: для любой пары не соединенных ребром вершин есть вершина, связанная с обеими этими вершинами. Как устроен такой граф?&lt;br /&gt;
# Докажите, что для любого графа $G$ можно записать в каждой вершине $u$ такое число $d(u)$, что числа $d(u)$ и $d(v)$ имеют общий делитель, отличный от 1, тогда и только тогда, когда в графе $G$ есть ребро $uv$.&lt;br /&gt;
# Граф называется кубическим, если степень всех вершин равна 3. Три вершины графа образуют треугольник, если они попарно соединены ребром. Постройте кубический граф с $n$ вершинами, не содержащий треугольников.&lt;br /&gt;
# Граф называется самодополнительным, если он изоморфен своему дополнению. Приведите примеры самодополнительных графов с 4 и 5 вершинами. Докажите, что если граф является самодополнительным, то он содержит либо $4n$ либо $4n+1$ вершину для некоторого целого положительного $n$.&lt;br /&gt;
# Докажите, что для любого целого положительного $n$ существует самодополнительный граф, содержащий $4n$ вершин, а также самодополнительный граф, содержащий $4n+1$ вершину.&lt;br /&gt;
# Граф $G$ с $n$ вершинами называется графом пересечений, если можно найти такие множества $U_i$, $i$ от 1 до $n$, что вершины $i$ и $j$ связаны ребром тогда и только тогда, когда $U_i \cap U_j \ne \varnothing$. Докажите, что любой граф является графом пересечений.&lt;br /&gt;
# Числом пересечения графа $\omega(G)$ называется минимальная возможная мощность множества $S$, что граф $G$ является графом пересечений для множеств $U_i \subset S$. Опишите графы с $\omega(G) = 1$.&lt;br /&gt;
# Приведите пример графа с $\omega(G) = 2$.&lt;br /&gt;
# Приведите пример графа с $n$ вершинами, для которого $\omega(G) &amp;gt; n$.&lt;br /&gt;
# Докажите, что для любого графа с $n$ вершинами, где $n \ge 4$, выполнено $\omega(G) \le n^2/4$.&lt;br /&gt;
# Обозначим как $C_n$ цикл из $n$ вершин. Найдите $\omega(C_n)$.&lt;br /&gt;
# Найдите асимптотическое поведение $\omega(\overline{C_n})$.&lt;br /&gt;
# Колесом $C_n + K_1$ называется граф, состоящий из цикла, содержащего $n$ вершин, и еще одной вершины $u$, причем все вершины цикла соединены с $u$. Найдите $\omega(C_n + K_1)$. &lt;br /&gt;
# Докажите, что каждый циклический путь нечетной длины содержит простой цикл.&lt;br /&gt;
# Докажите или опровергните, что объединение двух любых простых путей из вершины $u$ в вершину $v$ содержит цикл.&lt;br /&gt;
# Докажите, что граф связен тогда и только тогда когда для любого разбиения его множества вершин $V$ на два непустых непересекающихся множества $X$ и $Y$ существует ребро, соединяющее эти множества.&lt;br /&gt;
# Докажите, что в связном графе любые два самых длинных простых пути имеют общую вершину.&lt;br /&gt;
# Докажите или опровергните, что в связном графе все самые длинные простые пути имеют общую вершину.&lt;br /&gt;
# Обозначим как $\delta(G)$ минимальную степень вершины в графе. Докажите, что если в графе с $n$ вершинами $\delta(G) &amp;gt; (n - 1) / 2$, то он связен.&lt;br /&gt;
# Докажите, что либо граф $G$, либо его дополнение $\overline{G}$ связен.&lt;br /&gt;
# Будем говорить, что $G$ связан короткими путями, если между любыми двумя вершинами в $G$ есть путь длины не более 3. Докажите, что либо $G$, либо $\overline G$ связан короткими путями.&lt;br /&gt;
# Найдите максимальное число ребер в графе с $n$ вершинами, не содержащем четных простых циклов.&lt;br /&gt;
# Докажите, что граф с $n$ вершинами и $n + 4$ ребрами содержит два простых цикла, не имеющих общих ребер.&lt;br /&gt;
# Доказать или опровергнуть, что если ребро $uv$ - мост, то $u$ и $v$ - точки сочленения.&lt;br /&gt;
# Доказать или опровергнуть, что если $u$ и $v$ - точки сочленения, то $uv$ - мост.&lt;br /&gt;
# Какое максимальное число точек сочленения может быть в графе с $n$ вершинами?&lt;br /&gt;
# Рассмотрим отношение на рёбрах - $R$. $ab R cd$, если 1) $ab$ и $cd$ имеют общую вершину; 2) $ab$ и $cd$ лежат на цикле. Доказать, что вершинная двусвязность - это $R^*$.&lt;br /&gt;
# Доказать, что ребро $uv$ - мост тогда и только тогда, когда $uv$ вершинно двусвязно только с самим собой.&lt;br /&gt;
# Каждое дерево является двудольным графом. А какие деревья являются полными двудольными графами?&lt;br /&gt;
# Доказать, что следующие четыре утверждения для связного графа $G$ эквивалентны: (1) любое ребро является мостом (2) $G$ является деревом (3) любой блок $G$ является $K_2$ (4) любое непустое пересечение связных подграфов $G$ связно.&lt;br /&gt;
# Доказать, что следующие четыре утверждения для связного графа $G$ эквивалентны: (1) $G$ содержит ровно один простой цикл (2) число вершин и ребер $G$ совпадает (3) $G$ можно превратить в дерево удалением ровно одного ребра (4) множество ребер $G$, которые не являются мостами, образуют один простой цикл.&lt;br /&gt;
# Обозначим как $\lambda(G)$ минимальное число ребер, которое нужно удалить в графе, чтобы он потерял связность, $\kappa(G)$ - минимальное число вершин, которое нужно удалить в графе, чтобы он потерял связность (для полного графа полагаем $\kappa(G)=n-1$). Докажите, что $\kappa(G) \le \lambda(G) \le \delta(G)$.&lt;br /&gt;
# Докажите. что для любых $1 \le \kappa(G) \le \lambda(G) \le \delta(G)$ существует граф $G$ с такими параметрами.&lt;br /&gt;
# Докажите, что не существует графов с $\kappa(G) = 3$ и 7 ребрами.&lt;br /&gt;
# Докажите, что любой кубический граф, который содержит точку сочленения, содержит также мост.&lt;br /&gt;
# Пусть $G$ - полный двудольный граф, за исключением $K_{2,2}$. Докажите $\lambda(G)=\delta(G)$, почем единственный способ удалить $\lambda(G)$ ребер, чтобы граф потерял связность - удалить все ребра, инцидентные одной из вершин.&lt;br /&gt;
# Докажите, что если в связном графе любой блок эйлеров, то и весь граф эйлеров.&lt;br /&gt;
# Граф называется произвольно вычерчиваемым из вершины $u$, если следующая процедура всегда приводит к эйлеровому циклу: начиная с вершины $u$, переходим каждый раз по любому исходящему из текущей вершины ребру, по которому ранее не проходили. Докажите, что эйлеров граф является произвольно вычерчиваемым из $u$, если любой его простой цикл содержит $u$.&lt;br /&gt;
# Докажите, что если граф $G$ является произвольно вычерчиваемым из $u$, то $u$ имеет максимальную степень в $G$.&lt;br /&gt;
# Докажите, что если граф $G$ является произвольно вычерчиваемым из $u$, то либо $u$ - единственная точка сочленения в $G$, либо в $G$ нет точек сочленения.&lt;br /&gt;
# Доказать или опровегнуть, что если $G$ содержит порожденный тета-подграф (две вершины, соединенные тремя путями), то $G$ не гамильтонов.&lt;br /&gt;
# Обозначим как $G^3$ граф, в котором две вершины соединены, если они соединены в $G$ путем длины не более 3. Докажите, что если $G$ связен, то $G^3$ гамильтонов.&lt;br /&gt;
# Граф называется произвольно гамильтоновым, если следующая процедура всегда приводит к гамильтонову циклу: начиная с произвольной вершины $u$, переходим каждый раз по любому исходящему из текущей вершины ребру, другой конец которого мы ранее не посещали, либо обратно в вершину $u$, если непосещенных соседей нет. Опишите все произвольно гамильтоновы графы.&lt;br /&gt;
# Теорема &amp;quot;Антихватала&amp;quot;. Докажите, что если не выполнено условие теоремы Хватала, то найдется граф с такой степенной последовательностью, не содержащий гамильтонова цикла.&lt;br /&gt;
# Докажите, что если сумма степеней любых двух несмежных вершин графа $G$ не меньше $n+1$, то любые две различные вершины $G$ можно соединить гамильтоновым путем.&lt;br /&gt;
# Докажите, что для любого $k$ существует негамильтонов граф с $\kappa(G)=k$.&lt;br /&gt;
# Обозначим как $G^2$ граф, в котором две вершины соединены, если они соединены в $G$ путем длины не более 2. Докажите, что если $G$ вершинно двусвязен, то $G^2$ гамильтонов.&lt;br /&gt;
# Докажите теорему Гуйя-Ури: если в ориентированном графе у любой вершины как входящая, так и исходящая степень хотя бы $n/2$, то он гамильтонов.&lt;br /&gt;
# Докажите усиленную версию теоремы Редеи-Камеона: в любом сильно связном турнире с $n$ вершинами есть простой цикл любой длины от $3$ до $n$.&lt;br /&gt;
# Докажите, что различные деревья имеют различные коды Прюфера.&lt;br /&gt;
# Докажите, что наименьшее число вершин в кубическом графе, в котором есть мост, равно 10.&lt;br /&gt;
# Докажите, что если $v$ {{---}} точка сочленения в $G$, то $v$ не точка сочленения в $\overline G$.&lt;br /&gt;
# Опишите все деревья с диаметром 2.&lt;br /&gt;
# Опишите все деревья с диаметром 3.&lt;br /&gt;
# Реберным графом для графа $G$ называется граф $G_E$, множество вершин которого совпадает с множеством ребер исходного графа, два ребра $e$ и $f$ соединены ребром в реберном графе, если у них есть общая инцидентная вершина. Докажите или опровергните, что если $G$ является эйлеровым, то реберный граф является гамильтоновым.&lt;br /&gt;
# Докажите или опровергните, что если $G_E$ является гамильтоновым, то граф $G$ является эйлеровым.&lt;br /&gt;
# В каком случае ребра реберного графа можно разбить на полные подграфы таким образом, чтобы каждая вершина принадлежала в точности двум из подграфов?&lt;br /&gt;
# Выразите число треугольников в реберном графе $G_E$ через число треугольников графа $G$ и набор его степеней.&lt;br /&gt;
# В каком случае связный граф $G$ имеет регулярный реберный граф?&lt;br /&gt;
# Постройте граф $G$ с $n \ge 4$ вершинами, для которого граф $G_E$ не эйлеров, а граф $G_E^2$ эйлеров.&lt;br /&gt;
# Докажите, что если $G$ содержит $n \ge 5$ вершин, то если $G_E^2$ эйлеров, то и $G_E^3$ эйлеров.&lt;br /&gt;
# Постройте минимальный по числу вершин реберный граф, в котором нет гамильтонова цикла.&lt;br /&gt;
# Докажите, что $G_E$ гамильтонов тогда и только тогда, когда граф $G$ содержит циклический реберно простой путь, содержащий хотя бы одну вершину, инцидентную каждому ребру графа $G$.&lt;br /&gt;
# Докажите, что число помеченных неподвешенных деревьев есть $n^{n-2}$, используя теорему Кирхгофа.&lt;br /&gt;
# Сколько остовных деревьев у полного двудольного графа $K_{n,m}$?&lt;br /&gt;
# Докажите или опровергните, что если в связном графе любой максимальный по включению простой путь (путь, к которому нельзя добавить ребро в начало или в конец) является диаметром, то такой граф является деревом.&lt;br /&gt;
# Опишите дерево с кодом Прюфера $(i, i,\ldots , i)$.&lt;br /&gt;
# Опишите деревья, в коде Прюфера которых нет одинаковых чисел.&lt;br /&gt;
# Зафиксируем дерево $T$. Рассмотрим функцию от вершины $x$: $d(x) = \sum_v dist(x, v)$, где $dist(x, v)$ - расстояние между вершинами $x$ и $v$ в ребрах. Пусть $y$ и $z$ - различные соседи вершины $x$. Докажите, что $2d(x) &amp;lt; d(y) + d(z)$.&lt;br /&gt;
# Центром дерева называется вершина $x$, для которой $max_v(dist(x, v))$ минимален. Докажите, что у дерева 1 или 2 центра, и любой центр дерева лежит на его любом диаметре.&lt;br /&gt;
# Барицентром дерева называется вершина $x$, для которой $\sum_v(dist(x, v))$ минимальная. Докажите, что у дерева 1 или 2 барицентра.&lt;br /&gt;
# Докажите, что для любого $k$ существует дерево, для которого расстояние между центром и барицентром не меньше $k$.&lt;br /&gt;
# Докажите, что если в связном графе есть реберно простой цикл длины $k$, то у графа есть не менее $k$ остовных деревьев.&lt;br /&gt;
# Приведите пример графа с двумя непересекающимися остовными деревьями.&lt;br /&gt;
# Какое максимальное количество попарно непересекающихся остовных деревьев может быть в графе с $n$ вершинами?&lt;br /&gt;
# Пусть связный граф $G$ имеет диаметр $d$. Докажите или опровергните, что у $G$ есть остовное дерево с диаметром $d$.&lt;br /&gt;
# Рассмотрим множество остовных деревьев связного графа $G$. Построим граф $S_G$, вершинами которого являются остовные деревья $G$, а две вершины $T_1$ и $T_2$ соединены ребром, если дерево $T_2$ можно получить из $T_1$ удалением одного ребра и добавлением другого. Докажите, что $S_G$ является связным.&lt;br /&gt;
# Докажите, что две вершины $T_1$ и $T_2$ в $S_G$ соединены ребром тогда и только тогда, когда их объединение содержит ровно один простой цикл.&lt;br /&gt;
# Пусть связный граф $G$ содержит $n$ вершин, докажите, что диаметр $S_G$ не превышает $n - 1$. &lt;br /&gt;
# Приведите пример связного графа $G$, содержащего $n$ вершин, для которого граф $S_G$ имеет диаметр $n - 1$. &lt;br /&gt;
# Докажите, что для любого $1 \le k \le n - 1$ существует связный граф $G$, содержащий $n$ вершин, такой что диаметр $S_G$ не превышает $n - k$.&lt;br /&gt;
# Графы $G_1$, содержащий $n_1$ вершин и $m_1$ ребер, и $G_2$, содержащий $n_2$ вершин и $m_2$ ребер, гомеоморфны. Докажите, что $n_1+m_2 = n_2+m_1$.&lt;br /&gt;
# Докажите, что планарный эйлеров граф содержит эйлеров цикл, не имеющий самопересечений.&lt;br /&gt;
# Пусть планарный граф $G$ без петель и параллельных ребер содержит $n$ вершин. Какое максимальное число ребер он может содержать?&lt;br /&gt;
# Приведите пример духсвязного планарного графа, который не является гамильтоновым.&lt;br /&gt;
# Докажите, что планарный четырехсвязный граф гамильтонов.&lt;br /&gt;
# Пусть $G$ - планарный граф, в котором каждый треугольник ограничивает область, не содержащую ребер, причем добавление любого ребра нарушает это свойство. Докажите, что $G$ гамильтонов.&lt;br /&gt;
# Докажите или опровергните, что циклы вокруг конечных граней образуют базис циклического пространства планарного графа.&lt;br /&gt;
# Докажите, что любой трехсвязный планарный граф имеет остов, у которого наибольшая степень равна 3.&lt;br /&gt;
# Докажите, что все колеса самодвойственны.&lt;br /&gt;
# Найдите максимальное $k$, что граф $K_k$ можно уложить на торе.&lt;br /&gt;
# Найдите максимальное $k$, что граф $K_k$ можно уложить на сфере с двумя ручками.&lt;br /&gt;
# Докажите, что для любого $m$ существует $k$, такое что граф с $K_k$ нельзя уложить на сфере с $m$ ручками.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D1%8C%D1%8F_%D0%AD%D0%B9%D0%BB%D0%B5%D1%80%D0%BE%D0%B2%D0%B0_%D0%BE%D0%B1%D1%85%D0%BE%D0%B4%D0%B0&amp;diff=62112</id>
		<title>Деревья Эйлерова обхода</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D1%8C%D1%8F_%D0%AD%D0%B9%D0%BB%D0%B5%D1%80%D0%BE%D0%B2%D0%B0_%D0%BE%D0%B1%D1%85%D0%BE%D0%B4%D0%B0&amp;diff=62112"/>
				<updated>2017-10-25T18:37:16Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Представление деревьев в виде эйлерова графа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Задача о динамической связности==&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Для динамически изменяющегося дерева выполнить следующие запросы:&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{link(u, w)}&amp;lt;/tex&amp;gt;''' {{---}} добавить ребро &amp;lt;tex&amp;gt;(u, w)&amp;lt;/tex&amp;gt; (при условии, что вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; принадлежат разным деревьям),&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{cut(u, w)}&amp;lt;/tex&amp;gt;''' {{---}} разрезать ребро &amp;lt;tex&amp;gt;(u, w)&amp;lt;/tex&amp;gt; (при условии, что ребро &amp;lt;tex&amp;gt;(u, w)&amp;lt;/tex&amp;gt; принадлежит дереву),&lt;br /&gt;
* '''&amp;lt;tex&amp;gt;\mathrm{isConnected(u, w)}&amp;lt;/tex&amp;gt;''' {{---}} определить принадлежат ли вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; одной компоненте связности.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для решения поставленной задачи будем представлять дерево в виде его [[Эйлеровость графов|эйлерова графа]], а затем будем работать с [[Эйлеровость графов|эйлеровым обходом]] (англ.''Euler tour tree'') этого графа. Это позволит выполнять указанные запросы за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Представление деревьев в виде эйлерова графа==&lt;br /&gt;
&lt;br /&gt;
[[Файл:Tree.png|300px|thumb|left|Пример дерева]]&lt;br /&gt;
[[Файл:Euler graph.png|300px|thumb|right|Соответствующий эйлеров граф]]&lt;br /&gt;
&lt;br /&gt;
Для представления [[Дерево, эквивалентные определения|дерева]] в виде [[Эйлеровость графов|эйлерового графа]] заменим каждое ребро &amp;lt;tex&amp;gt;\{u, v\} \&amp;lt;/tex&amp;gt; дерева на два ребра &amp;lt;tex&amp;gt;(u, v)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получившийся [[Основные определения теории графов|ориентированный граф]] будет эйлеровым согласно [[Эйлеровость графов|критерию]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Представим дерево в виде последовательности вершин, посещенных в порядке эйлерова обхода, начиная с вершины &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;.&lt;br /&gt;
[[Файл:Tour1.png|thumb|320px|center]]&lt;br /&gt;
&lt;br /&gt;
==Операции c эйлеровыми обходами==&lt;br /&gt;
&lt;br /&gt;
===Добавление ребра===&lt;br /&gt;
&lt;br /&gt;
Для добавления ребра &amp;lt;tex&amp;gt;(c, g)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
*Выберем любое вхождение вершины &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; в эйлеров обход дерева &amp;lt;tex&amp;gt;T1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Разрежем эйлеров обход &amp;lt;tex&amp;gt;T1&amp;lt;/tex&amp;gt; на две части:&lt;br /&gt;
*: &amp;lt;tex&amp;gt;A1&amp;lt;/tex&amp;gt; {{---}} часть обхода до выбранного вхождения вершины &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, включая ее.&lt;br /&gt;
*: &amp;lt;tex&amp;gt;A2&amp;lt;/tex&amp;gt; {{---}} часть обхода после выбранного вхождения вершины &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;, включая ее.&lt;br /&gt;
*Аналогично, выберем любое вхождение вершины &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в эйлеров обход дерева &amp;lt;tex&amp;gt;T2&amp;lt;/tex&amp;gt; и разрежем его на две части &amp;lt;tex&amp;gt;B1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Соберем результирующий эйлеров обход в порядке &amp;lt;tex&amp;gt;A1, B2, B1&amp;lt;/tex&amp;gt; (без первой повторяющейся вершины), &amp;lt;tex&amp;gt;A2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы быстро находить место, где разрезать эйлеровы обходы деревьев &amp;lt;tex&amp;gt;T1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T2&amp;lt;/tex&amp;gt;, будем хранить эйлеровы обходы в двоичных деревьях поиска. &lt;br /&gt;
Ключом вершины для построения дерева поиска будет время посещения этой вершины эйлеровым обходом.&lt;br /&gt;
Для каждой вершины дерева &amp;lt;tex&amp;gt;(T1, T2)&amp;lt;/tex&amp;gt; будем хранить указатель на вершину в дереве поиска, которая соответствует вхождению вершины дерева в эйлеров обход. &lt;br /&gt;
Тогда за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; переходим от вершины дерева к вершине дерева поиска, по которой за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; можно будет разделить дерево поиска на две части.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Link22.png |thumb|400px|center|Рис.1a Исходный лес &amp;lt;br&amp;gt;Рис.1b Эйлеровы обходы деревьев&amp;lt;br&amp;gt; Рис.1с Двоичные деревья поиска для хранения эйлеровых обходов &amp;lt;br&amp;gt; Рис.1d Результирующий эйлеров обход]]&lt;br /&gt;
&lt;br /&gt;
===Разрезание ребра===&lt;br /&gt;
&lt;br /&gt;
Для удаления ребра &amp;lt;tex&amp;gt;(g, j)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
*Найдем в эйлеровом обходе дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; две пары посещений концов удаляемого ребра &amp;lt;tex&amp;gt;g,j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j,g&amp;lt;/tex&amp;gt;, которые соответствуют прохождениям по ребру &amp;lt;tex&amp;gt;(g, j)&amp;lt;/tex&amp;gt; в дереве &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Разрежем эйлеров обход дерева по этим парам на три части: &amp;lt;tex&amp;gt;A1, A2, A3&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Соединив &amp;lt;tex&amp;gt;A1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A3&amp;lt;/tex&amp;gt; (без повторяющейся первой вершины), получим эйлеров обход первого дерева, а &amp;lt;tex&amp;gt;A2&amp;lt;/tex&amp;gt; дает эйлеров обход второго дерева.&lt;br /&gt;
&lt;br /&gt;
Чтобы быстро находить места в эйлеровом обходе, которые соответствуют прохождению удаляемого ребра в дереве, будем для каждого ребра в дереве хранить ссылку на те места эйлерова обхода, где последовательно посещаем концы удаляемого ребра.&lt;br /&gt;
Так, для ребра &amp;lt;tex&amp;gt;(g, j)&amp;lt;/tex&amp;gt; храним ссылки на узлы дерева поиска, соответствующие парам посещений концов этого ребра.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Link23.png |thumb|400px|center|Рис.1a Исходное дерево &amp;lt;br&amp;gt;Рис.1b Эйлеров обход исходного дерева&amp;lt;br&amp;gt; Рис.1с Двоичное дерево поиска для хранения эйлерового обхода &amp;lt;br&amp;gt; Рис.1d Эйлеровы обходы получившихся деревьев]]&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;O(\log n)&amp;lt;/tex&amp;gt;&amp;lt;ref&amp;gt;[http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.109.4875&amp;amp;rep=rep1&amp;amp;type=pdf Ron Wein {{---}} Efficient Implementation of Red-Black Trees.]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Декартово дерево по неявному ключу===&lt;br /&gt;
&lt;br /&gt;
Также, можем хранить последовательности вершин эйлерова обхода в [[Декартово_дерево_по_неявному_ключу|декартовом дереве по неявному ключу]]. Глубина декартового дерева, построенного на массиве из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, будет поддерживаться равной &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Операции объединения и разделения так же выполняются за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Link-Cut Tree]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Euler_tour_technique Wikipedia {{---}} Euler tour technique]&lt;br /&gt;
* [http://courses.csail.mit.edu/6.851/spring07/scribe/lec05.pdf Advanced Data Structures {{---}} Euler tour trees]&lt;br /&gt;
* [http://codeforces.com/blog/entry/18369?mobile=true&amp;amp;locale=en CodeForces {{---}} On Euler tour trees]&lt;br /&gt;
* [http://logic.pdmi.ras.ru/csclub/node/2819 Лекториум{{---}} Лекция Павла Маврина об эйлеровых обходах]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Обходы графов]]&lt;br /&gt;
[[Категория: Эйлеровы графы]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_FIRST_%D0%B8_FOLLOW&amp;diff=61037</id>
		<title>Построение FIRST и FOLLOW</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_FIRST_%D0%B8_FOLLOW&amp;diff=61037"/>
				<updated>2017-05-28T14:49:34Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Для данной [[LL(k)-грамматики, множества FIRST и FOLLOW#defLLK | LL(1)-грамматики]] оказывается возможным построить нисходящий рекурсивный парсер, который по слову сможет построить его дерево разбора в грамматике или сказать, что слово не принадлежит языку грамматики. Более того, становится возможной даже автоматическая генерация парсеров для таких грамматик&amp;lt;ref&amp;gt;[http://www.antlr.org/ ANTLR {{---}} Parser generator] &amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы написать парсер для LL(1)-грамматики, необходимо построить [[LL(k)-грамматики, множества FIRST и FOLLOW#deffirst | множества]] &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt;, после чего по ним можно составить таблицу синтаксического анализатора.&lt;br /&gt;
== Построение FIRST ==&lt;br /&gt;
Для построения &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; воспользуемся несколькими леммами, которые следуют прямо из определения. Пусть &amp;lt;tex&amp;gt; \alpha, \beta &amp;lt;/tex&amp;gt; {{---}} цепочки из терминалов и нетерминалов, &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; {{---}} символ из алфавита.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafirst1&lt;br /&gt;
|author=1&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt; \mathrm{FIRST}(\alpha \beta) = \mathrm{FIRST}(\alpha) \cup (\mathrm{FIRST}(\beta)\ \mathrm{if}\ \varepsilon \in \mathrm{FIRST}(\alpha)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Рассмотрим лемму подробней. Пусть правило из нетерминала &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; имеет вид &amp;lt;tex&amp;gt; A \to X_1 X_2 \dots X_k &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; X_i,\ (1 \leqslant i \leqslant k) &amp;lt;/tex&amp;gt; {{---}} произвольный терминал или нетерминал. Тогда по лемме в &amp;lt;tex&amp;gt; \mathrm{FIRST}[A] &amp;lt;/tex&amp;gt; нужно добавить &amp;lt;tex&amp;gt; \mathrm{FIRST}(X_i) &amp;lt;/tex&amp;gt;, если для всех &amp;lt;tex&amp;gt; 1 \leqslant j &amp;lt; i &amp;lt;/tex&amp;gt; верно, что &amp;lt;tex&amp;gt; X_j \Rightarrow^* \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafirst2 &lt;br /&gt;
|author=2&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FIRST}(c \alpha) = \{c\}&amp;lt;/tex&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FIRST}(\varepsilon) = \{\varepsilon \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
Алгоритм строит для каждого нетерминала грамматики &amp;lt;tex&amp;gt;\Gamma = \langle \Sigma, N, S, P \rangle&amp;lt;/tex&amp;gt; отображение в множество символов. Перед запуском алгоритма необходимо избавиться от [[Удаление бесполезных символов из грамматики | бесполезных символов]]. Изначально каждое правило отображается в пустое множество.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''function''' constructFIRST():&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;( A  \in N )&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;\mathrm{FIRST}[A] =  \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
      changed = ''true''&lt;br /&gt;
      '''while''' changed&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;( A \to \alpha \in P )&amp;lt;/tex&amp;gt;&lt;br /&gt;
              &amp;lt;tex&amp;gt; \mathrm{FIRST}[A]\ \cup =\ \mathrm{FIRST}(\alpha) &amp;lt;/tex&amp;gt;&lt;br /&gt;
              changed = ''true'' '''if''' &amp;lt;tex&amp;gt; \mathrm{FIRST}[A] &amp;lt;/tex&amp;gt; изменился          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=proposalfirstcorrect &lt;br /&gt;
|statement=Приведённый алгоритм правильно строит множество &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для данной грамматики.&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \Leftarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм на каждом шаге использует [[#lemmafirst1 | леммы]], чтобы построить списки &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для каждого нетерминала. Поэтому он добавит только те терминалы, которые на самом деле лежат в &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \Rightarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Покажем, что алгоритм найдёт все символы из множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Предположим, что в грамматике возможен вывод &amp;lt;tex&amp;gt; A \Rightarrow^* c \gamma &amp;lt;/tex&amp;gt;, и алгоритм не включил &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; \mathrm{FIRST}[A] &amp;lt;/tex&amp;gt;. Докажем индукцией по числу шагов &amp;lt;tex&amp;gt; \mathrm{while} &amp;lt;/tex&amp;gt;, что этого не может быть.&lt;br /&gt;
&lt;br /&gt;
Пусть за &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; шагов алгоритм добавит символы &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для каждого нетерминала &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt; A \Rightarrow^k c \gamma &amp;lt;/tex&amp;gt;. База индукции для числа шагов &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; верна, если считать, что для всех терминалов нам известны &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;. Если алгоритм корректно отрабатывает на &amp;lt;tex&amp;gt;(k-1)&amp;lt;/tex&amp;gt;-ом шаге, то он правильно отработает их на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ом шаге, потому что&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; A \Rightarrow \beta \Rightarrow^{k-1} c \gamma &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для &amp;lt;tex&amp;gt; \beta &amp;lt;/tex&amp;gt; алгоритм правильно построил &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; по предположению индукции, а для &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; он правильно построит по [[#lemmafirst1 | леммам]], следовательно, переход доказан.&lt;br /&gt;
&lt;br /&gt;
К тому же, алгоритм завершится за конечное число шагов, так как в &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для каждого нетерминала не может добавиться больше символов, чем есть в алфавите.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Построение FOLLOW ==&lt;br /&gt;
Сформулируем похожие утверждения для построения &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafollow1 &lt;br /&gt;
|author=3&lt;br /&gt;
|statement=Для каждого правила &amp;lt;tex&amp;gt; A \to \alpha B \beta &amp;lt;/tex&amp;gt; верно, что &amp;lt;tex&amp;gt;(\mathrm{FIRST}(\beta) \setminus \{\varepsilon\}) \subset \mathrm{FOLLOW}(B) &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafollow2 &lt;br /&gt;
|author=4&lt;br /&gt;
|statement=Для каждого правила вида &amp;lt;tex&amp;gt; A \to \alpha B &amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt; A \to \alpha B \beta,\ \varepsilon \in \mathrm{FIRST}(\beta)&amp;lt;/tex&amp;gt; верно, что &amp;lt;tex&amp;gt;\mathrm{FOLLOW}(A) \subset \mathrm{FOLLOW}(B) &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
Реализация построения &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; получается сразу из [[#lemmafollow1 | лемм]]. Для алгоритма сначала требуется выполнить построение &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для грамматики.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''function''' constructFOLLOW():&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;( A  \in N )&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;\mathrm{FOLLOW}[A] =  \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;\mathrm{FOLLOW}[S] =  \{\$\} &amp;lt;/tex&amp;gt;  &amp;lt;font color=green&amp;gt; // в стартовый нетерминал помещается символ конца строки &amp;lt;/font&amp;gt;&lt;br /&gt;
      changed = ''true''&lt;br /&gt;
      '''while''' changed&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;( A \to \alpha \in P )&amp;lt;/tex&amp;gt;&lt;br /&gt;
              '''for''' &amp;lt;tex&amp;gt;( B : \alpha = \beta B \gamma)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                  &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B]\ \cup =\ \mathrm{FIRST}(\gamma) \setminus \{\varepsilon\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
                  '''if''' &amp;lt;tex&amp;gt; \varepsilon \in \mathrm{FIRST}(\gamma) &amp;lt;/tex&amp;gt;&lt;br /&gt;
                      &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B]\ \cup =\ \mathrm{FOLLOW}[A]&amp;lt;/tex&amp;gt;&lt;br /&gt;
                  changed = ''true'' '''if''' &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B] &amp;lt;/tex&amp;gt; изменился&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Корректность данного алгоритма доказывается точно так же, как и корректность алгоритма конструирования &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Пример ==&lt;br /&gt;
Рассмотрим, как будут строиться множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; на примере грамматики арифметических выражений. Ограничимся только операциями сложения, умножения и наличием скобок. Числа будем обозначать одной буквой &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; для простоты. Интуитивная грамматика для арифметических выражений выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; E \to E + E \mid E \times E \mid (E) \mid n &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Однако данная грамматика содержит [[Устранение левой рекурсии | левую рекурсию]], [[LL(k)-грамматики, множества FIRST и FOLLOW#Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW | правое ветвление]] и является [[Существенно неоднозначные языки#defambigous |неоднозначной]]. Чтобы избавиться от данных проблем неявно, можно придумать более удачную грамматику для рассматриваемого языка. Например, она может иметь следующий вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; &lt;br /&gt;
E \to T + E \mid T \\&lt;br /&gt;
T \to F \times T \mid F \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная грамматика содержит только правое ветвление, от которого можно избавиться левой факторизацией, после чего грамматика примет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; &lt;br /&gt;
E \to TE' \\&lt;br /&gt;
E' \to +E \mid \varepsilon \\&lt;br /&gt;
T \to FT' \\&lt;br /&gt;
T' \to \times T \mid \varepsilon \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А затем для простоты анализирования раскрыть нетерминалы &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; в правилах для &amp;lt;tex&amp;gt; E' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; T' &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; &lt;br /&gt;
E \to TE' \\&lt;br /&gt;
E' \to +TE' \mid \varepsilon \\&lt;br /&gt;
T \to FT' \\&lt;br /&gt;
T' \to \times FT' \mid \varepsilon \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Конструирование FIRST для арифметических выражений ===&lt;br /&gt;
Рассмотрим, как будет выглядеть множество &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; после очередной итераций цикла &amp;lt;tex&amp;gt; \mathrm{while} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''После 1ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 2ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 3eй итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
Далее никаких изменений происходить не будет, и на этом алгоритм завершит свою работу.&lt;br /&gt;
=== Конструирование FOLLOW для арифметических выражений ===&lt;br /&gt;
Теперь рассмотрим построение таблицы &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; после каждой итераций цикла &amp;lt;tex&amp;gt; \mathrm{while} &amp;lt;/tex&amp;gt;. Стартовым нетерминалом будет &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt;, поэтому в него добавим сразу &amp;lt;tex&amp;gt; \$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''До цикла while:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$ \ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 1ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$ \ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 2ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 3ей итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ ,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
На этом построение множества &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; для грамматики закончится.&lt;br /&gt;
&lt;br /&gt;
=== Итоговая таблица ===&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ ,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Используя [[LL(k)-грамматики, множества FIRST и FOLLOW#Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW | теорему]], можно убедиться, что грамматика арифметических выражений на самом деле является LL(1)-грамматикой.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/LL_parser Wikipedia {{---}} LL parser]&lt;br /&gt;
* [http://citforum.ru/programming/theory/serebryakov/4.shtml СitForum {{---}} Синтаксический анализ]&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. ISBN 5-8459-0189-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Нисходящий разбор]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_FIRST_%D0%B8_FOLLOW&amp;diff=61035</id>
		<title>Построение FIRST и FOLLOW</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_FIRST_%D0%B8_FOLLOW&amp;diff=61035"/>
				<updated>2017-05-28T14:48:54Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Для данной [[LL(k)-грамматики, множества FIRST и FOLLOW#defLLK | LL(1)-грамматики]] оказывается возможным построить нисходящий рекурсивный парсер, который по слову сможет построить его дерево разбора в грамматике или сказать, что слово не принадлежит языку грамматики. Более того, становится возможной даже автоматическая генерация парсеров для таких грамматик&amp;lt;ref&amp;gt;[http://www.antlr.org/ ANTLR {{---}} Parser generator] &amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Чтобы написать парсер для LL(1)-грамматики, необходимо построить [[LL(k)-грамматики, множества FIRST и FOLLOW#deffirst | множества]] &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt;, после чего по ним можно составить таблицу синтаксического анализатора.&lt;br /&gt;
== Построение FIRST ==&lt;br /&gt;
Для построения &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; воспользуемся несколькими леммами, которые следуют прямо из определения. Пусть &amp;lt;tex&amp;gt; \alpha, \beta &amp;lt;/tex&amp;gt; {{---}} цепочки из терминалов и нетерминалов, &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; {{---}} символ из алфавита.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafirst1&lt;br /&gt;
|author=1&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt; \mathrm{FIRST}(\alpha \beta) = \mathrm{FIRST}(\alpha) \cup (\mathrm{FIRST}(\beta)\ \mathrm{if}\ \varepsilon \in \mathrm{FIRST}(\alpha)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Рассмотрим лемму подробней. Пусть правило из нетерминала &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; имеет вид &amp;lt;tex&amp;gt; A \to X_1 X_2 \dots X_k &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; X_i,\ (1 \leqslant i \leqslant k) &amp;lt;/tex&amp;gt; {{---}} произвольный терминал или нетерминал. Тогда по лемме в &amp;lt;tex&amp;gt; \mathrm{FIRST}[A] &amp;lt;/tex&amp;gt; нужно добавить &amp;lt;tex&amp;gt; \mathrm{FIRST}(X_i) &amp;lt;/tex&amp;gt;, если для всех &amp;lt;tex&amp;gt; 1 \leqslant j &amp;lt; i &amp;lt;/tex&amp;gt; верно, что &amp;lt;tex&amp;gt; X_j \Rightarrow^* \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafirst2 &lt;br /&gt;
|author=2&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FIRST}(c \alpha) = \{c\}&amp;lt;/tex&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FIRST}(\varepsilon) = \{\varepsilon \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
Алгоритм строит для каждого терминала грамматики &amp;lt;tex&amp;gt;\Gamma = \langle \Sigma, N, S, P \rangle&amp;lt;/tex&amp;gt; отображение в множество символов. Перед запуском алгоритма необходимо избавиться от [[Удаление бесполезных символов из грамматики | бесполезных символов]]. Изначально каждое правило отображается в пустое множество.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''function''' constructFIRST():&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;( A  \in N )&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;\mathrm{FIRST}[A] =  \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
      changed = ''true''&lt;br /&gt;
      '''while''' changed&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;( A \to \alpha \in P )&amp;lt;/tex&amp;gt;&lt;br /&gt;
              &amp;lt;tex&amp;gt; \mathrm{FIRST}[A]\ \cup =\ \mathrm{FIRST}(\alpha) &amp;lt;/tex&amp;gt;&lt;br /&gt;
              changed = ''true'' '''if''' &amp;lt;tex&amp;gt; \mathrm{FIRST}[A] &amp;lt;/tex&amp;gt; изменился          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|id=proposalfirstcorrect &lt;br /&gt;
|statement=Приведённый алгоритм правильно строит множество &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для данной грамматики.&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \Leftarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм на каждом шаге использует [[#lemmafirst1 | леммы]], чтобы построить списки &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для каждого нетерминала. Поэтому он добавит только те терминалы, которые на самом деле лежат в &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \Rightarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Покажем, что алгоритм найдёт все символы из множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Предположим, что в грамматике возможен вывод &amp;lt;tex&amp;gt; A \Rightarrow^* c \gamma &amp;lt;/tex&amp;gt;, и алгоритм не включил &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; \mathrm{FIRST}[A] &amp;lt;/tex&amp;gt;. Докажем индукцией по числу шагов &amp;lt;tex&amp;gt; \mathrm{while} &amp;lt;/tex&amp;gt;, что этого не может быть.&lt;br /&gt;
&lt;br /&gt;
Пусть за &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; шагов алгоритм добавит символы &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для каждого нетерминала &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt; A \Rightarrow^k c \gamma &amp;lt;/tex&amp;gt;. База индукции для числа шагов &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; верна, если считать, что для всех терминалов нам известны &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;. Если алгоритм корректно отрабатывает на &amp;lt;tex&amp;gt;(k-1)&amp;lt;/tex&amp;gt;-ом шаге, то он правильно отработает их на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ом шаге, потому что&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; A \Rightarrow \beta \Rightarrow^{k-1} c \gamma &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для &amp;lt;tex&amp;gt; \beta &amp;lt;/tex&amp;gt; алгоритм правильно построил &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; по предположению индукции, а для &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; он правильно построит по [[#lemmafirst1 | леммам]], следовательно, переход доказан.&lt;br /&gt;
&lt;br /&gt;
К тому же, алгоритм завершится за конечное число шагов, так как в &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для каждого нетерминала не может добавиться больше символов, чем есть в алфавите.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Построение FOLLOW ==&lt;br /&gt;
Сформулируем похожие утверждения для построения &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafollow1 &lt;br /&gt;
|author=3&lt;br /&gt;
|statement=Для каждого правила &amp;lt;tex&amp;gt; A \to \alpha B \beta &amp;lt;/tex&amp;gt; верно, что &amp;lt;tex&amp;gt;(\mathrm{FIRST}(\beta) \setminus \{\varepsilon\}) \subset \mathrm{FOLLOW}(B) &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmafollow2 &lt;br /&gt;
|author=4&lt;br /&gt;
|statement=Для каждого правила вида &amp;lt;tex&amp;gt; A \to \alpha B &amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt; A \to \alpha B \beta,\ \varepsilon \in \mathrm{FIRST}(\beta)&amp;lt;/tex&amp;gt; верно, что &amp;lt;tex&amp;gt;\mathrm{FOLLOW}(A) \subset \mathrm{FOLLOW}(B) &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
Реализация построения &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; получается сразу из [[#lemmafollow1 | лемм]]. Для алгоритма сначала требуется выполнить построение &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; для грамматики.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''function''' constructFOLLOW():&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;( A  \in N )&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;\mathrm{FOLLOW}[A] =  \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;\mathrm{FOLLOW}[S] =  \{\$\} &amp;lt;/tex&amp;gt;  &amp;lt;font color=green&amp;gt; // в стартовый нетерминал помещается символ конца строки &amp;lt;/font&amp;gt;&lt;br /&gt;
      changed = ''true''&lt;br /&gt;
      '''while''' changed&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;( A \to \alpha \in P )&amp;lt;/tex&amp;gt;&lt;br /&gt;
              '''for''' &amp;lt;tex&amp;gt;( B : \alpha = \beta B \gamma)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                  &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B]\ \cup =\ \mathrm{FIRST}(\gamma) \setminus \{\varepsilon\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
                  '''if''' &amp;lt;tex&amp;gt; \varepsilon \in \mathrm{FIRST}(\gamma) &amp;lt;/tex&amp;gt;&lt;br /&gt;
                      &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B]\ \cup =\ \mathrm{FOLLOW}[A]&amp;lt;/tex&amp;gt;&lt;br /&gt;
                  changed = ''true'' '''if''' &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B] &amp;lt;/tex&amp;gt; изменился&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Корректность данного алгоритма доказывается точно так же, как и корректность алгоритма конструирования &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Пример ==&lt;br /&gt;
Рассмотрим, как будут строиться множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; на примере грамматики арифметических выражений. Ограничимся только операциями сложения, умножения и наличием скобок. Числа будем обозначать одной буквой &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; для простоты. Интуитивная грамматика для арифметических выражений выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; E \to E + E \mid E \times E \mid (E) \mid n &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Однако данная грамматика содержит [[Устранение левой рекурсии | левую рекурсию]], [[LL(k)-грамматики, множества FIRST и FOLLOW#Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW | правое ветвление]] и является [[Существенно неоднозначные языки#defambigous |неоднозначной]]. Чтобы избавиться от данных проблем неявно, можно придумать более удачную грамматику для рассматриваемого языка. Например, она может иметь следующий вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; &lt;br /&gt;
E \to T + E \mid T \\&lt;br /&gt;
T \to F \times T \mid F \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная грамматика содержит только правое ветвление, от которого можно избавиться левой факторизацией, после чего грамматика примет вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; &lt;br /&gt;
E \to TE' \\&lt;br /&gt;
E' \to +E \mid \varepsilon \\&lt;br /&gt;
T \to FT' \\&lt;br /&gt;
T' \to \times T \mid \varepsilon \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А затем для простоты анализирования раскрыть нетерминалы &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; в правилах для &amp;lt;tex&amp;gt; E' &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; T' &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; &lt;br /&gt;
E \to TE' \\&lt;br /&gt;
E' \to +TE' \mid \varepsilon \\&lt;br /&gt;
T \to FT' \\&lt;br /&gt;
T' \to \times FT' \mid \varepsilon \\&lt;br /&gt;
F \to n \mid (E)&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Конструирование FIRST для арифметических выражений ===&lt;br /&gt;
Рассмотрим, как будет выглядеть множество &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; после очередной итераций цикла &amp;lt;tex&amp;gt; \mathrm{while} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''После 1ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 2ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 3eй итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
Далее никаких изменений происходить не будет, и на этом алгоритм завершит свою работу.&lt;br /&gt;
=== Конструирование FOLLOW для арифметических выражений ===&lt;br /&gt;
Теперь рассмотрим построение таблицы &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; после каждой итераций цикла &amp;lt;tex&amp;gt; \mathrm{while} &amp;lt;/tex&amp;gt;. Стартовым нетерминалом будет &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt;, поэтому в него добавим сразу &amp;lt;tex&amp;gt; \$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''До цикла while:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$ \ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 1ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$ \ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 2ой итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
'''После 3ей итерации:''' &lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ ,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
На этом построение множества &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; для грамматики закончится.&lt;br /&gt;
&lt;br /&gt;
=== Итоговая таблица ===&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;E'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \$,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;T'&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times,\ \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ +,\ \$\ ,\ )\ \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ n,\ (\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ \times, \ +,\ \$\ ,\ )\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Используя [[LL(k)-грамматики, множества FIRST и FOLLOW#Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW | теорему]], можно убедиться, что грамматика арифметических выражений на самом деле является LL(1)-грамматикой.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/LL_parser Wikipedia {{---}} LL parser]&lt;br /&gt;
* [http://citforum.ru/programming/theory/serebryakov/4.shtml СitForum {{---}} Синтаксический анализ]&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. ISBN 5-8459-0189-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Нисходящий разбор]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE%D0%B9_%D0%B2%D0%B5%D0%BB%D0%B8%D1%87%D0%B8%D0%BD%D1%8B&amp;diff=60870</id>
		<title>Математическое ожидание случайной величины</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE%D0%B9_%D0%B2%D0%B5%D0%BB%D0%B8%D1%87%D0%B8%D0%BD%D1%8B&amp;diff=60870"/>
				<updated>2017-05-21T21:12:54Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Пример 2 */ Karlukova Marina (darkblack1997) \dfrac&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Математическое ожидание случайной величины==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Математическое ожидание''' (англ. ''mean value'') (&amp;lt;tex&amp;gt;E\xi&amp;lt;/tex&amp;gt;) {{---}} мера среднего значения случайной величины, равна &amp;lt;tex&amp;gt;E\xi = \sum \xi(\omega)p(\omega)&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема &lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;\sum\limits_{\omega\epsilon\Omega} \xi(\omega)p(\omega) = \sum\limits_a a p(\xi = a)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof= &amp;lt;tex&amp;gt;\sum\limits_a \sum\limits_{\omega|\xi(\omega) = a} \xi(\omega)p(\omega) = \sum\limits_a a \sum\limits_{\omega|\xi(\omega)=a}p(\omega) = \sum\limits_a a p(\xi = 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; \xi(i) = i &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; E\xi = 1\cdot \genfrac{}{}{1pt}{0}{1}{6}+2\cdot \genfrac{}{}{1pt}{0}{1}{6} \dots +6\cdot \genfrac{}{}{1pt}{0}{1}{6} = 3.5&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Свойства математического ожидания==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|about=о матожидании константы&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt;E(a) = a&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a \in R&amp;lt;/tex&amp;gt; {{---}} константа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|about=о матожидании неравенств&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;0 \leqslant \xi \leqslant \eta&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;\eta&amp;lt;/tex&amp;gt; {{---}} случайная величина с конечным математическим ожиданием, то математическое ожидание случайной величины &amp;lt;tex&amp;gt;\xi&amp;lt;/tex&amp;gt; также конечно, и &amp;lt;tex&amp;gt;0 \leqslant E(\xi) \leqslant E(\eta)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|about=о матожидании случайной величины на событии вероятности нуль&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;\xi = \eta&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;E(\xi) = E(\eta)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|about=о матожидании двух независимых случайных величин&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;\xi&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\eta&amp;lt;/tex&amp;gt; {{---}} две независимые случайные величины, то &amp;lt;tex&amp;gt;E(\xi \cdot \eta) = E(\xi) \cdot E(\eta)&amp;lt;/tex&amp;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;E&amp;lt;/tex&amp;gt; линейно. &lt;br /&gt;
|proof=&lt;br /&gt;
# &amp;lt;tex&amp;gt;E(\xi + \eta) = {\sum_w \limits}(\xi(w) + \eta(w))p(w) = {\sum_w \limits}\xi(w)p(w) + {\sum_w \limits}\eta(w)p(w) = E(\xi) + E(\eta) &amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;E(\alpha\xi) = {\sum_w \limits}\alpha\xi(w) = \alpha{\sum_w \limits}\xi(w) = \alpha E(\xi)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\alpha&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;
===Пример 1===&lt;br /&gt;
Найти математическое ожидание суммы цифр на случайной кости домино.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; \xi &amp;lt;/tex&amp;gt; {{---}} случайная величина, которая возвращает первое число на кости домино, а &amp;lt;tex&amp;gt; \eta &amp;lt;/tex&amp;gt; {{---}} возвращает второе число.&lt;br /&gt;
Очевидно, что &amp;lt;tex&amp;gt; E(\xi)= E(\eta)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
Посчитаем &amp;lt;tex&amp;gt;E(\xi)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;E(\xi)={\sum_{i=0}^6 \limits}i \cdot p(\xi=i)={\sum_{i=0}^6 \limits}i \cdot \genfrac{}{}{1pt}{0}{1}{7}=3&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Получаем ответ&lt;br /&gt;
&amp;lt;tex&amp;gt;E(\xi+\eta)=2E(\xi)=6&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример 2===&lt;br /&gt;
Пусть у нас есть строка &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Строка &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; генерируется случайным образом так, что два подряд идущих символа неравны. Какое математическое ожидание количества совпавших символов? Считать что размер алфавита равен &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, а длина строки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим случайные величины &amp;lt;tex&amp;gt;\xi^i&amp;lt;/tex&amp;gt; {{---}} совпал ли у строк  &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-тый символ. &lt;br /&gt;
Найдем математическое ожидание этой величины&lt;br /&gt;
&amp;lt;tex&amp;gt;E(\xi^i)=0 \cdot p(\xi^i=0)+1 \cdot p(\xi^i=1)=p(s[i]=t[i])&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;s[i],t[i]&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-тые символы соответствующих строк.&lt;br /&gt;
Так как появление каждого символа равновероятно, то &amp;lt;tex&amp;gt;p(s[i]=t[i])=\dfrac{}{}{1pt}{0}{1}{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итоговый результат: &amp;lt;tex&amp;gt;E(\xi)={\sum_{i=1}^n \limits}E(\xi^i)=\dfrac{}{}{1pt}{0}{n}{k} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример 3===&lt;br /&gt;
Найти математическое ожидание количества инверсий на всех перестановках чисел от &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; \xi &amp;lt;/tex&amp;gt; {{---}} случайная величина, которая возвращает количество инверсий в перестановке.&lt;br /&gt;
&lt;br /&gt;
Очевидно, что вероятность любой перестановки равна &amp;lt;tex&amp;gt; \genfrac{}{}{1pt}{0}{1}{n!} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt; E\xi = \genfrac{}{}{1pt}{0}{1}{n!}\cdot{\sum_{i=1}^{n!} \limits}E(\xi^i) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; P = (p_1,p_2,\dots,p_n)&amp;lt;/tex&amp;gt; является перестановкой чисел &amp;lt;tex&amp;gt; 1, 2,\dots, n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt; A = (p_n, p_{n-1}, \dots, p_1) &amp;lt;/tex&amp;gt; является перевернутой перестановкой &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем, что количество инверсий в этих двух перестановках равно &amp;lt;tex&amp;gt; \genfrac{}{}{1pt}{0}{n\cdot(n-1)}{2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим все пары &amp;lt;tex&amp;gt; 1 \leqslant i &amp;lt; j \leqslant n &amp;lt;/tex&amp;gt;, таких пар всего &amp;lt;tex&amp;gt; \genfrac{}{}{1pt}{0}{n\cdot(n-1)}{2} &amp;lt;/tex&amp;gt;. Тогда пара этих чисел образуют инверсию или в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, или в &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; стоит раньше &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; в перестановке &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; будет стоять после &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и уже не будет давать инверсию. Аналогично, если &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; стоит раньше &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; в перестановке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Всего таких пар из перестановки и перевернутой перестановки будет &amp;lt;tex&amp;gt; \genfrac{}{}{1pt}{0}{n!}{2} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Итого: &amp;lt;tex&amp;gt; E\xi = \genfrac{}{}{1pt}{0}{1}{n!}\cdot\genfrac{}{}{1pt}{0}{n\cdot(n-1)}{2}\cdot\genfrac{}{}{1pt}{0}{n!}{2} = \genfrac{}{}{1pt}{0}{n\cdot(n-1)}{4} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примеры распределений==&lt;br /&gt;
&lt;br /&gt;
===Распределение Бернулли===&lt;br /&gt;
Случайная величина &amp;lt;tex&amp;gt;\xi&amp;lt;/tex&amp;gt; имеет распределение Бернулли, если она принимает всего два значения: &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; с вероятностями &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;q \equiv 1-p&amp;lt;/tex&amp;gt; соответственно. Таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;P(\xi = 1) = p&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;P(\xi = 0) = q&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда несложно догадаться, чему будет равно математическое ожидание:&lt;br /&gt;
:&amp;lt;tex&amp;gt;E(\xi) = 1 \cdot p + 0 \cdot q = p&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Гипергеометрическое распределение===&lt;br /&gt;
Гипергеометрическое распределение в теории вероятностей моделирует количество удачных выборок без возвращения из конечной совокупности.&lt;br /&gt;
&lt;br /&gt;
Пусть имеется конечная совокупность, состоящая из &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; элементов. Предположим, что &amp;lt;tex&amp;gt;D&amp;lt;/tex&amp;gt; из них обладают нужным нам свойством. Оставшиеся &amp;lt;tex&amp;gt;N-D&amp;lt;/tex&amp;gt; этим свойством не обладают. Случайным образом из общей совокупности выбирается группа из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Пусть &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} случайная величина, равная количеству выбранных элементов, обладающих нужным свойством. Тогда функция вероятности &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; имеет вид:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;P_\xi(k) \equiv P(\xi = k) = \genfrac{}{}{1pt}{0}{C_D^k \cdot C_{N-D}^{n-k}}{C_N^n}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt;C_n^k \equiv \genfrac{}{}{1pt}{0}{n!}{k! \cdot (n-k)!}&amp;lt;/tex&amp;gt; обозначает биномиальный коэффициент.&lt;br /&gt;
&lt;br /&gt;
Гипергеометрическое распределение обозначается &amp;lt;tex&amp;gt; \xi \sim \mathrm{HG}(D,N,n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Формула математического ожидания для гипергеометрического распределения имеет вид:&lt;br /&gt;
:&amp;lt;tex&amp;gt;E(\xi) = \genfrac{}{}{1pt}{0}{n \cdot D}{N}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Смотри также==&lt;br /&gt;
* [[Дисперсия случайной величины]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Математическое_ожидание Wikipedia {{---}} Математическое ожидание]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/Гипергеометрическое_распределение Wikipedia {{---}} Гипергеометрическое распределение]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/Распределение_Бернулли Wikipedia {{---}} Распределение Бернулли]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория вероятности]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0,_%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D0%B0%D1%8F_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;diff=60087</id>
		<title>Дерево поиска, наивная реализация</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0,_%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D0%B0%D1%8F_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;diff=60087"/>
				<updated>2017-01-18T22:40:44Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Восстановление дерева по результату обхода preorderTraversal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Файл:Binary_search_tree.svg.png|right|300px|thumb|Бинарное дерево поиска из 9 элементов]]'''Бинарное дерево поиска''' (англ. ''binary search tree, BST'') {{---}} структура данных для работы с [[Упорядоченное множество|упорядоченными множествами]].&lt;br /&gt;
Бинарное дерево поиска обладает следующим свойством: если &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} узел бинарного дерева с ключом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, то все узлы в левом поддереве должны иметь ключи, меньшие &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, а в правом поддереве большие &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
== Операции в бинарном дереве поиска ==&lt;br /&gt;
Для представления бинарного дерева поиска в памяти будем использовать следующую структуру:&lt;br /&gt;
 '''struct''' Node:&lt;br /&gt;
   '''T''' key                    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// ключ узла&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''Node''' left                &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// указатель на левого потомка&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''Node''' right               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// указатель на правого потомка&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''Node''' parent              &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// указатель на предка&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Обход дерева поиска ===&lt;br /&gt;
Есть три операции обхода узлов дерева, отличающиеся порядком обхода узлов:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{inorderTraversal}&amp;lt;/tex&amp;gt; {{---}} обход узлов в отсортированном порядке,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{preorderTraversal}&amp;lt;/tex&amp;gt; {{---}} обход узлов в порядке: вершина, левое поддерево, правое поддерево,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathrm{postorderTraversal}&amp;lt;/tex&amp;gt; {{---}} обход узлов в порядке: левое поддерево, правое поддерево, вершина.&lt;br /&gt;
 '''func''' inorderTraversal(x : '''Node'''):&lt;br /&gt;
    '''if''' x != ''null''&lt;br /&gt;
       inorderTraversal(x.left)&lt;br /&gt;
       '''print''' x.key&lt;br /&gt;
       inorderTraversal(x.right)&lt;br /&gt;
При выполнении данного обхода вершины будут выведены в следующем порядке: ''1 3 4 6 7 8 10 13 14''.&lt;br /&gt;
&lt;br /&gt;
 '''func''' preorderTraversal(x : '''Node''')&lt;br /&gt;
    '''if''' x != ''null''&lt;br /&gt;
       '''print''' x.key&lt;br /&gt;
       preorderTraversal(x.left)&lt;br /&gt;
       preorderTraversal(x.right)&lt;br /&gt;
При выполнении данного обхода вершины будут выведены в следующем порядке: ''8 3 1 6 4 7 10 14 13''.&lt;br /&gt;
&lt;br /&gt;
 '''func''' postorderTraversal(x : '''Node''')&lt;br /&gt;
    '''if''' x != ''null''&lt;br /&gt;
       postorderTraversal(x.left)&lt;br /&gt;
       postorderTraversal(x.right)&lt;br /&gt;
       '''print''' x.key&lt;br /&gt;
При выполнении данного обхода вершины будут выведены в следующем порядке: ''1 4 7 6 3 13 14 10 8''.&lt;br /&gt;
&lt;br /&gt;
Данные алгоритмы выполняют обход за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, поскольку процедура вызывается ровно два раза для каждого узла дерева.&lt;br /&gt;
&lt;br /&gt;
=== Поиск элемента ===&lt;br /&gt;
[[Файл:Bst search.png|frame|right|318px|Поиск элемента 4]]&lt;br /&gt;
Для поиска элемента в бинарном дереве поиска можно воспользоваться следующей функцией, которая принимает в качестве параметров корень дерева и искомый ключ. Для каждого узла функция сравнивает значение его ключа с искомым ключом. Если ключи одинаковы, то функция возвращает текущий узел, в противном случае функция вызывается рекурсивно для левого или правого поддерева. Узлы, которые посещает функция образуют нисходящий путь от корня, так что время ее работы &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; {{---}} высота дерева.&lt;br /&gt;
&amp;lt;div style=&amp;quot;width: 65%&amp;quot;&amp;gt;&lt;br /&gt;
 '''Node''' search(x : '''Node''', k : '''T'''):&lt;br /&gt;
    '''if''' x == ''null'' '''or''' k == x.key&lt;br /&gt;
       '''return''' x&lt;br /&gt;
    '''if''' k &amp;lt; x.key&lt;br /&gt;
       '''return''' search(x.left, k)&lt;br /&gt;
    '''else'''&lt;br /&gt;
       '''return''' search(x.right, k)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Поиск минимума и максимума ===&lt;br /&gt;
Чтобы найти минимальный элемент в бинарном дереве поиска, необходимо просто следовать указателям &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; от корня дерева, пока не встретится значение &amp;lt;tex&amp;gt;null&amp;lt;/tex&amp;gt;. Если у вершины есть левое поддерево, то по свойству бинарного дерева поиска в нем хранятся все элементы с меньшим ключом. Если его нет, значит эта вершина и есть минимальная. Аналогично ищется и максимальный элемент. Для этого нужно следовать правым указателям.&lt;br /&gt;
 '''Node''' minimum(x : '''Node'''):&lt;br /&gt;
   '''if''' x.left == ''null''&lt;br /&gt;
      '''return''' x&lt;br /&gt;
   '''return''' minimum(x.left)&lt;br /&gt;
&lt;br /&gt;
 '''Node''' maximum(x : '''Node'''):&lt;br /&gt;
   '''if''' x.right == ''null''&lt;br /&gt;
      '''return''' x&lt;br /&gt;
   '''return''' maximum(x.right)&lt;br /&gt;
Данные функции принимают корень поддерева, и возвращают минимальный (максимальный) элемент в поддереве. Обе процедуры выполняются за время &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Поиск следующего и предыдущего элемента ===&lt;br /&gt;
====Реализация с использованием информации о родителе====&lt;br /&gt;
Если у узла есть правое поддерево, то следующий за ним элемент будет минимальным элементом в этом поддереве. Если у него нет правого поддерева, то нужно следовать вверх, пока не встретим узел, который является левым дочерним узлом своего родителя. Поиск предыдущего выполнятся аналогично. Если у узла есть левое поддерево, то следующий за ним элемент будет максимальным элементом в этом поддереве. Если у него нет левого поддерева, то нужно следовать вверх, пока не встретим узел, который является правым дочерним узлом своего родителя. &lt;br /&gt;
 '''Node''' next(x : '''Node'''):&lt;br /&gt;
    '''if''' x.right != ''null''&lt;br /&gt;
       '''return''' minimum(x.right)&lt;br /&gt;
    y = x.parent&lt;br /&gt;
    '''while''' y != ''null'' '''and''' x == y.right&lt;br /&gt;
       x = y&lt;br /&gt;
       y = y.parent&lt;br /&gt;
    '''return''' y&lt;br /&gt;
&lt;br /&gt;
 '''Node''' prev(x : '''Node'''):&lt;br /&gt;
    '''if''' x.left != ''null''&lt;br /&gt;
       '''return''' maximum(x.left)&lt;br /&gt;
    y = x.parent&lt;br /&gt;
    '''while''' y != ''null'' '''and''' x == y.left&lt;br /&gt;
       x = y&lt;br /&gt;
       y = y.parent&lt;br /&gt;
    '''return''' y&lt;br /&gt;
Обе операции выполняются за время &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Реализация без использования информации о родителе====&lt;br /&gt;
Рассмотрим поиск следующего элемента для некоторого ключа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Поиск будем начинать с корня дерева, храня текущий узел &amp;lt;tex&amp;gt;current&amp;lt;/tex&amp;gt; и узел &amp;lt;tex&amp;gt;successor&amp;lt;/tex&amp;gt;, последний посещенный узел, ключ которого больше &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
Спускаемся вниз по дереву, как в алгоритме поиска узла. Рассмотрим ключ текущего узла &amp;lt;tex&amp;gt;current&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;current.key \leqslant x&amp;lt;/tex&amp;gt;, значит следующий за &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; узел находится в правом поддереве (в левом поддереве все ключи меньше &amp;lt;tex&amp;gt;current.key&amp;lt;/tex&amp;gt;). Если же &amp;lt;tex&amp;gt;x &amp;lt; current.key&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;x &amp;lt; next(x) \leqslant current.key&amp;lt;/tex&amp;gt;, поэтому &amp;lt;tex&amp;gt;current&amp;lt;/tex&amp;gt; может быть следующим для ключа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, либо следующий узел содержится в левом поддереве &amp;lt;tex&amp;gt;current&amp;lt;/tex&amp;gt;. Перейдем к нужному поддереву и повторим те же самые действия.&amp;lt;br&amp;gt;&lt;br /&gt;
Аналогично реализуется операция поиска предыдущего элемента.&lt;br /&gt;
 '''Node''' next(x : '''T'''):&lt;br /&gt;
    '''Node''' current = root, successor = ''null''                &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// root {{---}} корень дерева&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' current != ''null''&lt;br /&gt;
       '''if''' current.key &amp;gt; x&lt;br /&gt;
          successor = current&lt;br /&gt;
          current = current.left&lt;br /&gt;
       '''else'''&lt;br /&gt;
          current = current.right&lt;br /&gt;
    '''return''' successor&lt;br /&gt;
=== Вставка ===&lt;br /&gt;
Операция вставки работает аналогично поиску элемента, только при обнаружении у элемента отсутствия ребенка нужно подвесить на него вставляемый элемент.&lt;br /&gt;
====Реализация с использованием информации о родителе====&lt;br /&gt;
 '''func''' insert(x : '''Node''', z : '''Node'''):            &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// x {{---}} корень поддерева, z {{---}} вставляемый элемент&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' x != ''null''&lt;br /&gt;
      '''if''' z.key &amp;gt; x.key&lt;br /&gt;
         '''if''' x.right != ''null''&lt;br /&gt;
            x = x.right&lt;br /&gt;
         '''else'''&lt;br /&gt;
            z.parent = x&lt;br /&gt;
            x.right = z&lt;br /&gt;
            '''break'''&lt;br /&gt;
      '''else if''' z.key &amp;lt; x.key&lt;br /&gt;
         '''if''' x.left != ''null''&lt;br /&gt;
            x = x.left&lt;br /&gt;
         '''else'''&lt;br /&gt;
            z.parent = x&lt;br /&gt;
            x.left = z&lt;br /&gt;
            '''break'''&lt;br /&gt;
====Реализация без использования информации о родителе====&lt;br /&gt;
 '''Node''' insert(x : '''Node''', z : '''T'''):               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// x {{---}} корень поддерева, z {{---}} вставляемый ключ&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' x == ''null'' &lt;br /&gt;
       '''return''' Node(z)                        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// подвесим Node с key = z&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''else if''' z &amp;lt; x.key&lt;br /&gt;
       x.left = insert(x.left, z)&lt;br /&gt;
    '''else if''' z &amp;gt; x.key&lt;br /&gt;
       x.right = insert(x.right, z)&lt;br /&gt;
    '''return''' x&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма для обеих реализаций {{---}} &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Удаление ===&lt;br /&gt;
====Нерекурсивная реализация====&lt;br /&gt;
Для удаления узла из бинарного дерева поиска нужно рассмотреть три возможные ситуации. Если у узла нет дочерних узлов, то у его родителя нужно просто заменить указатель на &amp;lt;tex&amp;gt;null&amp;lt;/tex&amp;gt;. Если у узла есть только один дочерний узел, то нужно создать новую связь между родителем удаляемого узла и его дочерним узлом. Наконец, если у узла два дочерних узла, то нужно найти следующий за ним элемент (у этого элемента не будет левого потомка), его правого потомка подвесить на место найденного элемента, а удаляемый узел заменить найденным узлом. Таким образом, свойство бинарного дерева поиска не будет нарушено. Данная реализация удаления не увеличивает высоту дерева. Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;5&amp;quot; cellspacing=&amp;quot;0&amp;quot; &lt;br /&gt;
 !Случай&lt;br /&gt;
 !Иллюстрация&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Удаление листа'''&lt;br /&gt;
 |  [[Файл:Bst_del1.png |581px]]  &lt;br /&gt;
 |-&lt;br /&gt;
 |'''Удаление узла с одним дочерним узлом'''&lt;br /&gt;
 | [[Файл:Bst_del2.png |604px]]  &lt;br /&gt;
 |-&lt;br /&gt;
 |'''Удаление узла с двумя дочерними узлами'''&lt;br /&gt;
 | [[Файл:Bst_del3.png‎|900px]]&lt;br /&gt;
 |}&lt;br /&gt;
 '''func''' delete(t : '''Node''', v : '''Node'''):                 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; {{---}} дерево, &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; {{---}} удаляемый элемент&amp;lt;/font&amp;gt;&lt;br /&gt;
    p = v.parent                                  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// предок удаляемого элемента&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''if''' v.left == ''null'' '''and''' v.right == ''null''         &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// первый случай: удаляемый элемент - лист&amp;lt;/font&amp;gt;&lt;br /&gt;
      '''if''' p.left == v&lt;br /&gt;
        p.left = ''null''&lt;br /&gt;
      '''if''' p.right == v&lt;br /&gt;
        p.right = ''null''&lt;br /&gt;
    '''else if''' v.left == ''null'' '''or''' v.right == ''null''     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// второй случай: удаляемый элемент имеет одного потомка&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' v.left == ''null''                 &lt;br /&gt;
            '''if''' p.left == v&lt;br /&gt;
              p.left = v.right&lt;br /&gt;
            '''else'''&lt;br /&gt;
              p.right = v.right&lt;br /&gt;
            v.right.parent = p &lt;br /&gt;
        '''else'''&lt;br /&gt;
            '''if''' p.left == v&lt;br /&gt;
                p.left = v.left&lt;br /&gt;
            '''else'''&lt;br /&gt;
                p.right = v.left&lt;br /&gt;
            v.left.parent = p&lt;br /&gt;
    '''else'''                                          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// третий случай: удаляемый элемент имеет двух потомков&amp;lt;/font&amp;gt;&lt;br /&gt;
      successor = next(v, t)                   &lt;br /&gt;
      v.key = successor.key&lt;br /&gt;
      '''if''' successor.parent.left == successor&lt;br /&gt;
        successor.parent.left = successor.right&lt;br /&gt;
        '''if''' successor.right != ''null''&lt;br /&gt;
          successor.right.parent = successor.parent&lt;br /&gt;
      '''else'''&lt;br /&gt;
        successor.parent.right = successor.right&lt;br /&gt;
        '''if''' successor.right != ''null''&lt;br /&gt;
          successor.right.parent = successor.parent&lt;br /&gt;
&lt;br /&gt;
====Рекурсивная реализация====&lt;br /&gt;
При рекурсивном удалении узла из бинарного дерева нужно рассмотреть три случая: удаляемый элемент находится в левом поддереве текущего поддерева, удаляемый элемент находится в правом поддереве или удаляемый элемент находится в корне. В двух первых случаях нужно рекурсивно удалить элемент из нужного поддерева. Если удаляемый элемент находится в корне текущего поддерева и имеет два дочерних узла, то нужно заменить его минимальным элементом из правого поддерева и рекурсивно удалить минимальный элемент из правого поддерева. Иначе, если удаляемый элемент имеет один дочерний узел, нужно заменить его потомком. Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Рекурсивная функция, возвращающая дерево с удаленным элементом &amp;lt;tex&amp;gt;z&amp;lt;/tex&amp;gt;:&lt;br /&gt;
 '''Node''' delete(root : '''Node''', z : '''T'''):               &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// корень поддерева, удаляемый ключ&amp;lt;/font&amp;gt;&lt;br /&gt;
   '''if''' root == ''null''&lt;br /&gt;
     '''return''' root&lt;br /&gt;
   '''if''' z &amp;lt; root.key&lt;br /&gt;
     root.left = delete(root.left, z)&lt;br /&gt;
   '''else if''' z &amp;gt; root.key&lt;br /&gt;
     root.right = delete(root.right, z)&lt;br /&gt;
   '''else if''' root.left != ''null'' '''and''' root.right != ''null''&lt;br /&gt;
     root.key = minimum(root.right).key&lt;br /&gt;
     root.right = delete(root.right, root.right.key)&lt;br /&gt;
   '''else'''&lt;br /&gt;
     '''if''' root.left != ''null''&lt;br /&gt;
       root = root.left&lt;br /&gt;
     '''else'''&lt;br /&gt;
       root = root.right&lt;br /&gt;
   '''return''' root&lt;br /&gt;
&lt;br /&gt;
==Задачи о бинарном дереве поиска==&lt;br /&gt;
&lt;br /&gt;
===Проверка того, что заданное дерево является деревом поиска===&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Определить, является ли заданное двоичное дерево деревом поиска.&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Not_Enough.png|right|thumb|291px|Пример дерева, для которого недостаточно проверки лишь его соседних вершин]]&lt;br /&gt;
Для того чтобы решить эту задачу, применим [[Обход в глубину, цвета вершин|обход в глубину]]. Запустим от корня рекурсивную логическую функцию, которая выведет &amp;lt;tex&amp;gt;\mathtt{true}&amp;lt;/tex&amp;gt;, если дерево является BST и &amp;lt;tex&amp;gt;\mathtt{false}&amp;lt;/tex&amp;gt; в противном случае. Чтобы дерево не являлось BST, в нём должна быть хотя бы одна вершина, которая не попадает под определение дерева поиска. То есть достаточно найти всего одну такую вершину, чтобы выйти из рекурсии и вернуть значение &amp;lt;tex&amp;gt;\mathtt{false}&amp;lt;/tex&amp;gt;. Если же, дойдя до листьев, функция не встретит на своём пути такие вершины, она вернёт значение &amp;lt;tex&amp;gt;\mathtt{true}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Функция принимает на вход исследуемую вершину, а также два значения: &amp;lt;tex&amp;gt;\mathtt{min}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{max}&amp;lt;/tex&amp;gt;, которые до вызова функции равнялись &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; соответственно, где &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt; — очень большое число, т.е. ни один ключ дерева не превосходит его по модулю. Казалось бы, два последних параметра не нужны. Но без них программа может выдать неверный ответ, так как сравнения только вершины и её детей недостаточно. Необходимо также помнить, в каком поддереве для более старших предков мы находимся. Например, в этом дереве вершина с номером &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; находится левее вершины, в которой лежит &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;, чего не должно быть в дереве поиска, однако после проверки функция бы вернула &amp;lt;tex&amp;gt;\mathtt{true}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''bool''' isBinarySearchTree(root: '''Node'''):                    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Здесь root — корень заданного двоичного дерева.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   '''bool''' check(v : '''Node''', min: '''T''', max: '''T'''):                 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// min и max — минимально и максимально допустимые значения в вершинах поддерева.&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''if''' v == ''null''                    '''return''' ''true''&lt;br /&gt;
     '''if''' v.key &amp;lt;= min '''or''' max &amp;lt;= v.key '''return''' ''false''&lt;br /&gt;
     '''return''' check(v.left, min, v.key) '''and''' check(v.right, v.key, max)&lt;br /&gt;
 &lt;br /&gt;
   '''return''' check(root, &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество вершин в дереве.&lt;br /&gt;
&lt;br /&gt;
===Задачи на поиск максимального BST в заданном двоичном дереве===&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Найти в данном дереве такую вершину, что она будет корнем поддерева поиска с наибольшим количеством вершин.&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;, идя от корня и проверяя все вершины по одному разу, основываясь на следующих фактах:&lt;br /&gt;
* Значение в вершине больше максимума в её левом поддереве;&lt;br /&gt;
* Значение в вершине меньше минимума в её правом поддереве;&lt;br /&gt;
* Левое и правое поддерево являются деревьями поиска.&lt;br /&gt;
&lt;br /&gt;
Введём &amp;lt;tex&amp;gt;\mathtt{v.min}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{v.max}&amp;lt;/tex&amp;gt;, которые будут хранить минимум в левом поддереве вершины и максимум в правом. Тогда мы должны будем проверить, являются ли эти поддеревья деревьями поиска и, если да, лежит ли ключ вершины &amp;lt;tex&amp;gt;\mathtt{v}&amp;lt;/tex&amp;gt; между этими значениями &amp;lt;tex&amp;gt;\mathtt{v.min}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{v.max}&amp;lt;/tex&amp;gt;.  Если вершина является листом, она автоматически становится деревом поиска, а её ключ {{---}} минимумом или максимумом для её родителя (в зависимости от расположения вершины). Функция &amp;lt;tex&amp;gt;\mathtt{cnt}&amp;lt;/tex&amp;gt; записывает в &amp;lt;tex&amp;gt;\mathtt{v.kol}&amp;lt;/tex&amp;gt; количество вершин в дереве, если оно является деревом поиска или &amp;lt;tex&amp;gt;\mathtt{-1}&amp;lt;/tex&amp;gt; в противном случае. После выполнения функции ищем за линейное время вершину с наибольшим значением &amp;lt;tex&amp;gt;\mathtt{v.kol}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''int''' count(root: '''Node'''):                 &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// root — корень заданного двоичного дерева.&amp;lt;/font&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   '''int''' cnt(v: '''Node'''):&lt;br /&gt;
     '''if''' v == ''null''&lt;br /&gt;
       v.kol = 0&lt;br /&gt;
       '''return''' = 0&lt;br /&gt;
     '''if''' cnt(v.left) != -1 '''and''' cnt(v.right) != -1&lt;br /&gt;
       '''if''' v.left == ''null'' '''and''' v.right == ''null''&lt;br /&gt;
         v.min = v.key&lt;br /&gt;
         v.max = v.key&lt;br /&gt;
         v.kol = 1&lt;br /&gt;
         '''return''' 1&lt;br /&gt;
       '''if''' v.left == ''null''&lt;br /&gt;
         '''if''' v.right.max &amp;gt; v.key&lt;br /&gt;
           v.min = v.key&lt;br /&gt;
           v.kol = cnt(v.right) + 1&lt;br /&gt;
           '''return''' v.kol&lt;br /&gt;
       '''if''' v.right == ''null''&lt;br /&gt;
         '''if''' v.left.min &amp;lt; v.key&lt;br /&gt;
           v.max = v.key&lt;br /&gt;
           v.kol = cnt(v.left) + 1&lt;br /&gt;
           '''return''' v.kol&lt;br /&gt;
       '''if''' v.left.min &amp;lt; v.key '''and''' v.right.max &amp;gt; v.key &lt;br /&gt;
         v.min = v.left.min&lt;br /&gt;
         v.max = v.right.max&lt;br /&gt;
         v.kol = v.left.kol + v.right.kol + 1&lt;br /&gt;
         v.kol = cnt(v.left) + cnt(v.right) + 1&lt;br /&gt;
         '''return''' v.kol&lt;br /&gt;
     '''return''' -1&lt;br /&gt;
 &lt;br /&gt;
   '''return''' cnt(root)&lt;br /&gt;
&lt;br /&gt;
Алгоритм работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, так как мы прошлись по дереву два раза за время, равное количеству вершин.&lt;br /&gt;
&lt;br /&gt;
===Восстановление дерева по результату обхода preorderTraversal===&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Восстановить дерево по последовательности, выведенной после выполнения процедуры &amp;lt;tex&amp;gt;\mathrm{preorderTraversal}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:BST_from_seq.gif|right|thumb|257px|Восстановление дерева поиска по последовательности ключей]]&lt;br /&gt;
&lt;br /&gt;
Как мы помним, процедура &amp;lt;tex&amp;gt;\mathrm{preorderTraversal}&amp;lt;/tex&amp;gt; выводит значения в узлах поддерева следующим образом: сначала идёт до упора влево, затем на каком-то моменте делает шаг вправо и снова движется влево. Это продолжается до тех пор, пока не будут выведены все вершины. Полученная последовательность позволит нам однозначно определить расположение всех узлов поддерева. Первая вершина всегда будет в корне. Затем, пока не будут использованы все значения, будем последовательно подвешивать левых сыновей к последней добавленной вершине, пока не найдём номер, нарушающий убывающую последовательность, а для каждого такого номера будем искать вершину без правого потомка, хранящую наибольшее значение, не превосходящее того, которое хотим поставить, и подвешиваем к ней элемент с таким номером в качестве правого сына. Когда мы, желая найти такую вершину, встречаем какую-нибудь другую, уже имеющую правого сына, проходим по ветке вправо. Мы имеем на это право, так как если такая вершина стоит, то процедура обхода в ней уже побывала и поворачивала вправо, поэтому спускаться в другую сторону смысла не имеет. Вершину с максимальным ключом, с которой будем начинать поиск, будем запоминать. Она будет обновляться каждый раз, когда появится новый максимум.&lt;br /&gt;
&lt;br /&gt;
Процедура восстановления дерева работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Разберём алгоритм на примере последовательности &amp;lt;tex&amp;gt;\mathtt{8}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathtt{2}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathtt{1}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathtt{4}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathtt{3}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\mathtt{5}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем выделять красным цветом вершины, рассматриваемые на каждом шаге, чёрным жирным {{---}} их родителей, курсивом {{---}} убывающие подпоследовательности (в случаях, когда мы их рассматриваем) или претендентов на добавление к ним правого ребёнка (когда рассматривается вершина, нарушающая убывающую последовательность).&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Состояние &lt;br /&gt;
последовательности&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Действие&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Пояснение&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;|  &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''8'''&amp;lt;/span&amp;gt; 2 1 4 3 5&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Делаем вершину корнем.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''Первая вершина всегда будет корнем, так как вывод начинался с него.''&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| '''''8''''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''2'''''&amp;lt;/span&amp;gt; ''1'' 4 3 5&lt;br /&gt;
|rowspan=2 style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;|Находим убывающую подпоследовательность. Каждую вершину подвешиваем к последней из взятых ранее в качестве левого сына.&lt;br /&gt;
|rowspan=2 style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''Каждая последующая вершина становится левым сыном предыдущей, так как выводя ключи, мы двигались по дереву поиска влево, пока есть вершины.''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''8 '''2''''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''1'''''&amp;lt;/span&amp;gt; 4 3 5&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''8 '''2''''' 1 &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''4'''&amp;lt;/span&amp;gt; 3 5&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Для вершины, нарушившей убывающую последовательность, ищем максимальное значение, меньшее его. В данном случае оно равно &amp;lt;tex&amp;gt;\mathtt{2}&amp;lt;/tex&amp;gt;. Затем добавляем вершину.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''На моменте вывода следующего номера процедура обратилась уже к какому-то из правых поддеревьев, так как влево идти уже некуда. Значит, нам необходимо найти узел, для которого данная вершина являлась бы правым сыном. Очевидно, что в её родителе не может лежать значение, которое больше её ключа. Но эту вершину нельзя подвесить и к меньшим, иначе нашёлся бы более старший предок, также хранящий какое-то значение, которое меньше, чем в исследуемой. Для этого предка вершина бы попала в левое поддерево. И тогда возникает противоречие с определением дерева поиска. Отсюда следует, что родитель определяется единственным образом {{---}} он хранит максимум среди ключей, не превосходящих значения в подвешиваемой вершине, что и требовалось доказать.'' &lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| 8 2 1 '''''4''''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''3'''''&amp;lt;/span&amp;gt; 5&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Находим убывающую подпоследовательность. Каждую вершину подвешиваем к последней из взятых ранее в качестве левого сына.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''Зайдя в правое поддерево, процедура обхода снова до упора начала двигаться влево, поэтому действуем аналогичным образом.''&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''8'' 2 1 '''''4''''' 3 &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''5'''&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Для этой вершины ищем максимальное значение, меньшее его. Затем добавляем вершину.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| ''Здесь процедура снова обратилась к правому поддереву. Рассуждения аналогичны. Ключ родителя этой вершины равен &amp;lt;tex&amp;gt;\mathtt{4}&amp;lt;/tex&amp;gt;.'' &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Поисковые структуры данных]]&lt;br /&gt;
* [[Рандомизированное бинарное дерево поиска]]&lt;br /&gt;
* [[Красно-черное дерево]]&lt;br /&gt;
       &lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0 Википедия {{---}} Двоичное дерево поиска]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Binary_search_tree Wikipedia {{---}} Binary search tree]&lt;br /&gt;
* Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн, К. Алгоритмы: построение и анализ = Introduction to Algorithms / Под ред. И. В. Красикова. — 2-е изд. — М.: Вильямс, 2005. — 1296 с. — ISBN 5-8459-0857-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Деревья поиска]]&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Структуры данных]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B1%D1%83%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D1%81%D1%85%D0%B5%D0%BC%D0%BE%D0%B9_%D0%B8%D0%B7_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2&amp;diff=59101</id>
		<title>Реализация булевой функции схемой из функциональных элементов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B1%D1%83%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D1%81%D1%85%D0%B5%D0%BC%D0%BE%D0%B9_%D0%B8%D0%B7_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2&amp;diff=59101"/>
				<updated>2017-01-07T14:37:12Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.78.184: /* Источники */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Логические элементы ==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
'''Функциональный элемент''' (англ. ''Combinational element'')  — устройство, предназначенное для обработки информации в цифровой форме. Функциональный элемент имеет ''входы'' и ''выходы''.&lt;br /&gt;
Сигналы на входах функционального элемента — аргументы функции, которую реализует функциональный элемент, сигналы на выходах — значение функции от аргументов.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition=&lt;br /&gt;
Если входные и выходные сигналы — являются нулями и единицами, элемент называется '''логическим''' (англ. ''logic gate'').&lt;br /&gt;
При подаче на входы логического элемента любой комбинации двоичных сигналов, на выходах также возникает сигнал — значение [[Определение булевой функции|булевой функции]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Отождествление переменных осуществляется при помощи ветвления проводников.[[File:Отождествление.png|thumb|200px|Отождествление переменных]]&lt;br /&gt;
&lt;br /&gt;
Чтобы осуществить подстановку одной функции в другую нужно выход логического элемента, который реализует первую функцию, направить на вход логического элемента, который реализует вторую функцию.&lt;br /&gt;
[[File:Подстановка.png|thumb|200px|Подстановка]]&lt;br /&gt;
&lt;br /&gt;
== Изображение логических элементов на схемах ==&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; border = &amp;quot;1&amp;quot;&lt;br /&gt;
!Тип элемента&lt;br /&gt;
!-align=&amp;quot;center&amp;quot; |И&lt;br /&gt;
!-align=&amp;quot;center&amp;quot; |ИЛИ&lt;br /&gt;
!-align=&amp;quot;center&amp;quot; |НЕ&lt;br /&gt;
!Штрих Шеффера&lt;br /&gt;
!Стрелка Пирса&lt;br /&gt;
|-&lt;br /&gt;
!Традиционная форма&lt;br /&gt;
|[[Image:AND_logic_element.png]]&lt;br /&gt;
|[[Image:OR_logic_element.png]]&lt;br /&gt;
|[[Image:NOT_logic_element.png]]&lt;br /&gt;
|[[Image:NAND_logic_element.png]]&lt;br /&gt;
|[[Image:NOR_logic_element.png]]&lt;br /&gt;
|-&lt;br /&gt;
!Прямоугольная форма&lt;br /&gt;
|[[Image:AND_logic_relement.png]]&lt;br /&gt;
[[Image:AND_logic_relement2.png]]&lt;br /&gt;
|[[Image:OR_logic_relement.png]]&lt;br /&gt;
&lt;br /&gt;
[[Image:OR_logic_relement2.png]]&lt;br /&gt;
|[[Image:NOT_logic_relement.png]]&lt;br /&gt;
|[[Image:NAND_logic_relement.png]]&lt;br /&gt;
&lt;br /&gt;
[[Image:NAND_logic_relement2.png]]&lt;br /&gt;
|[[Image:NOR_logic_relement.png]]&lt;br /&gt;
[[Image:NOR_logic_relement2.png]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Схемная сложность ==&lt;br /&gt;
{{Определение&lt;br /&gt;
&lt;br /&gt;
|definition= '''Схемная сложность'''  (англ. ''Circuit complexity'') функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; относительно базиса &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;  — это минимальное количество функциональных элементов из набора &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, необходимое для реализации функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; в базисе &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Схемную сложность функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; в базисе &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; обозначают так: &amp;lt;tex&amp;gt;size_B(f)&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement =&lt;br /&gt;
Для любых базисов &amp;lt;tex&amp;gt;~B_1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;~B_2&amp;lt;/tex&amp;gt; и функции &amp;lt;tex&amp;gt;~f&amp;lt;/tex&amp;gt; верно неравенство &amp;lt;tex&amp;gt;~size_{B_2}(f) \le C_{(B_1,\;B_2)}size_{B_1}(f)&amp;lt;/tex&amp;gt;, где константа &amp;lt;tex&amp;gt;~C&amp;lt;/tex&amp;gt; зависит только от базисов &amp;lt;tex&amp;gt;~B_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;~B_2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof =&lt;br /&gt;
Пусть базис &amp;lt;tex&amp;gt;~B_2&amp;lt;/tex&amp;gt; состоит из функций &amp;lt;tex&amp;gt;~g_1, g_2, \ldots, g_n&amp;lt;/tex&amp;gt;. Каждый функциональный элемент базиса &amp;lt;tex&amp;gt;~B_2&amp;lt;/tex&amp;gt; можно собрать с помощью не более чем &amp;lt;tex&amp;gt;~size_{B_1}(g_i)&amp;lt;/tex&amp;gt; элементов из базиса &amp;lt;tex&amp;gt;~B_1&amp;lt;/tex&amp;gt;. Собрать &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; в базисе &amp;lt;tex&amp;gt;B_1&amp;lt;/tex&amp;gt; можно следующим образом: заменить каждый элемент схемы &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; в базисе &amp;lt;tex&amp;gt;B_2&amp;lt;/tex&amp;gt; на схему соответствующей функции в базисе &amp;lt;tex&amp;gt;B_1&amp;lt;/tex&amp;gt;. Такая сборка использует не более чем в &amp;lt;tex&amp;gt;~C = \overset{n}{\underset{i=1}{\max}} \ size_{B_1}(g_i)&amp;lt;/tex&amp;gt; раз больше функциональных элементов, чем соответствующая схема в &amp;lt;tex&amp;gt;B_2&amp;lt;/tex&amp;gt;. Параметр &amp;lt;tex&amp;gt;~C&amp;lt;/tex&amp;gt; зависит только от выбранных базисов.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Глубина схемы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
&lt;br /&gt;
|definition= '''Глубина схемы''' для функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; относительно базиса &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; (англ. ''Circuit depth'')  — это максимальная длина пути от входа до выхода по схеме соответствующей функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;, состоящей из элементов набора &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, где за единицу длины принимается один элемент схемы. &lt;br /&gt;
Глубину схемы для функции &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; в базисе &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; обозначают &amp;lt;tex&amp;gt;depth_B(f)&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Примечание: понятие глубины имеет смысл только для схем с ограниченной степенью входа (''bounded fan-in'').&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;~B_1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;~B_2&amp;lt;/tex&amp;gt; и функции &amp;lt;tex&amp;gt;~f&amp;lt;/tex&amp;gt; верно неравенство &amp;lt;tex&amp;gt;~depth_{B_2}(f) \leq C_{(B_1,\;B_2)}depth_{B_1}(f)&amp;lt;/tex&amp;gt;, где константа &amp;lt;tex&amp;gt;~C&amp;lt;/tex&amp;gt; зависит только от базисов &amp;lt;tex&amp;gt;~B_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;~B_2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Доказательство аналогично доказательству предыдущей теоремы.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Простейшие методы синтеза схем из функциональных элементов]]&lt;br /&gt;
* [[Сумматор]]&lt;br /&gt;
* [[Каскадный сумматор]]&lt;br /&gt;
* [[Контактная схема]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации==&lt;br /&gt;
&lt;br /&gt;
* Кормен, Т., Лейзерсон, Ч., Ривест, Р. Алгоритмы: построение и анализ — 960 с. — ISBN 5-900916-37-5&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Logic_gate  Wikipedia — Lodic gate]&lt;br /&gt;
* [http://www.intuit.ru/department/calculate/lancalc/2/  Лекция &amp;quot;Схемы из функциональных элементов&amp;quot; в НОУ &amp;quot;ИНТУИТ&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Схемы из функциональных элементов ]]&lt;/div&gt;</summary>
		<author><name>188.227.78.184</name></author>	</entry>

	</feed>