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

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50821</id>
		<title>Циркуляция потока</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50821"/>
				<updated>2016-01-07T15:26:02Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Поток нулевой величины в [[Определение сети, потока|сети]] $G(V, E)$ называется '''циркуляцией''' (англ. ''circulation problem''). Каждое ребро $e_i$ имеет $l_i$ и $c_i$ {{---}} минимальная и максимальная пропускная способности соответственно. Необходимо выяснить, существует ли в этой сети циркуляция, удовлетворяющая пропускным способностям рёбер. &lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Циркул2.png|frame|справа|Рисунок 1. Пример графа и циркуляции в нем (поток/пропуск.способность)]]&lt;br /&gt;
&lt;br /&gt;
Иначе говоря, [[Определение сети, потока#Определение потока|закон сохранения потока]] &amp;lt;tex&amp;gt;\sum\limits_v f(u,v)=0&amp;lt;/tex&amp;gt; должен выполняться для '''всех''' вершин графа, а значит нет нужды в истоке и стоке. Когда все  $l_i$ равны $0$, достаточно пустить поток нулевой величины из каждой вершины, что и будет ответом. Поэтому далее в графе будут существовать ребра с положительно нижней пропускной способностью.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Решение==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;Для решения этой задачи заменим исходную сеть $G$ на $G'$ следующим образом. Сначала добавим в граф вершины $s$ {{---}} исток и $t$ {{---}} сток. Для каждого ребра $e_i = v_{from} \xrightarrow{l_i, c_i} v_{to}$ добавим ребра $s \xrightarrow{0, l_i} v_{to}$ и $u_{from} \xrightarrow{0, l_i} t$, а также сделаем в ребре $e_i$ изменения: $c_i = c_i - l_i, l_i = 0$ (см. рисунок 2).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Циркуляция.png|frame|center|Рисунок 2. Слева - изначальный граф. Для каждого ребра заданы его нижняя и верхняя пропускные способности. Справа - граф после преобразований ребер.]]&lt;br /&gt;
&lt;br /&gt;
Каждое ребро изначального графа заменяется на три новых. Если по ребру $e_i = (v_{from}, v_{to})$ в исходной сети протекает поток $l_i \leqslant f_i \leqslant c_i$, то в новой сети по ребру $(s, v_{to})$ должен течь поток, равный $l_i$, то есть его пропускной способности. Поток, который вытекает из $v_{from}$ по ребру в $G$, заменяется на поток, который протекает по ребрам $(v_{from}, v_{to})$ и $(v_{from}, t)$ (поскольку сумма их пропускных способностей в полученном графе равна $c_i$). Аналогично, для вершины $v_{to}$ суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети $G'$ все $l_i = 0$, то есть мы имеем обыкновенную сеть.&lt;br /&gt;
&lt;br /&gt;
Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство &amp;lt;tex&amp;gt;\sum\limits_v f(u,v) = 0&amp;lt;/tex&amp;gt; для всех вершин графа. Это равносильно существованию потока между вершинами $s$ и $t$ в сети $G'$, который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит $i$-ое ребро как минимум на $l_i$, что и является необходимым требованием. Если этот поток существует, то будет выполнено:&lt;br /&gt;
* $\sum\limits_v f(u,v)=0,$ где $u \in V'-\{s,t\}, v \in V'$, то есть для всех исходных вершин;&lt;br /&gt;
* В $G': f_i \leqslant c_i - l_i \Rightarrow 0 \leqslant f_i \leqslant c_i - l_i \Rightarrow l_i \leqslant f_i + l_i \leqslant c_i$, что удовлетворяет всем ограничениям.&lt;br /&gt;
Значит, этот поток и есть циркуляция. &lt;br /&gt;
&lt;br /&gt;
Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети $G'$ соответствующие значения минимальной пропускной способности.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
Конструктор ребра принимает следующие аргументы:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{from}&amp;lt;/tex&amp;gt; {{---}} вершина начала ребра&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{to}&amp;lt;/tex&amp;gt; {{---}} вершина конца ребра&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{minCap}&amp;lt;/tex&amp;gt; {{---}} минимальная пропускная способность ребра&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{maxCap}&amp;lt;/tex&amp;gt; {{---}} максимальная пропускная способность ребра&lt;br /&gt;
 '''function''' circulation(&amp;lt;tex&amp;gt;V,E&amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt;G'=&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;V \cup s \cup t&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;)                                 &amp;lt;font color=green&amp;gt;// создаём новый граф с исходными вершинами и добавлением s и t {{---}} исток и сток&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.minCap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.maxCap - &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.minCap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.minCap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;G'=G' \cup &amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g \cup h \cup k&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     maxFlow = getMaxFlow(&amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;)                             &amp;lt;font color=green&amp;gt;// наибольший поток в графе G'&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;e : e\in E'&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from &amp;lt;tex&amp;gt;=s&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &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; &amp;lt; e&amp;lt;/tex&amp;gt;.maxCap                              &amp;lt;font color=green&amp;gt;// если для текущего ребра flow &amp;lt; cap&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''return''' false&lt;br /&gt;
     '''return''' true&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://dl.dropbox.com/u/39566886/Graph-Theory-Algorithms-M-Ashraf-Iqbal.pdf M. Ashraf Iqbal {{---}}'''Graph Theory and Algorithms''']&lt;br /&gt;
* [http://e-maxx.ru/algo/flow_with_limits MAXimal :: algo :: flow with limits]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Circulation_problem Wikipedia — Circulation problem]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50819</id>
		<title>Циркуляция потока</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50819"/>
				<updated>2016-01-07T15:08:13Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Поток нулевой величины в [[Определение сети, потока|сети]] $G(V, E)$ называется '''циркуляцией''' (англ. ''circulation problem''). Каждое ребро $e_i$ имеет $l_i$ и $c_i$ {{---}} минимальная и максимальная пропускная способности соответственно. Необходимо выяснить, существует ли в этой сети циркуляция, удовлетворяющая пропускным способностям рёбер. &lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Циркул2.png|frame|справа|Рисунок 1. Пример графа и циркуляции в нем (поток/пропуск.способность)]]&lt;br /&gt;
&lt;br /&gt;
Иначе говоря, [[Определение сети, потока#Определение потока|закон сохранения потока]] &amp;lt;tex&amp;gt;\sum\limits_v f(u,v)=0&amp;lt;/tex&amp;gt; должен выполняться для '''всех''' вершин графа, а значит нет нужды в истоке и стоке. Когда все  $l_i$ равны $0$, достаточно пустить поток нулевой величины из каждой вершины, что и будет ответом. Поэтому далее в графе будут существовать ребра с положительно нижней пропускной способностью.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Решение==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;Для решения этой задачи заменим исходную сеть $G$ на $G'$ следующим образом. Сначала добавим в граф вершины $s$ {{---}} исток и $t$ {{---}} сток. Для каждого ребра $e_i = v_{from} \xrightarrow{l_i, c_i} v_{to}$ добавим ребра $s \xrightarrow{0, l_i} v_{to}$ и $u_{from} \xrightarrow{0, l_i} t$, а также сделаем в ребре $e_i$ изменения: $c_i = c_i - l_i, l_i = 0$ (см. рисунок 2).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Циркуляция.png|frame|center|Рисунок 2. Слева - изначальный граф. Для каждого ребра заданы его нижняя и верхняя пропускные способности. Справа - граф после преобразований ребер.]]&lt;br /&gt;
&lt;br /&gt;
Каждое ребро изначального графа заменяется на три новых. Если по ребру $e_i = (v_{from}, v_{to})$ в исходной сети протекает поток $l_i \leqslant f_i \leqslant c_i$, то в новой сети по ребру $(s, v_{to})$ должен течь поток, равный $l_i$, то есть его пропускной способности. Поток, который вытекает из $v_{from}$ по ребру в $G$, заменяется на поток, который протекает по ребрам $(v_{from}, v_{to})$ и $(v_{from}, t)$ (поскольку сумма их пропускных способностей в полученном графе равна $c_i$). Аналогично, для вершины $v_{to}$ суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети $G'$ все $l_i = 0$, то есть мы имеем обыкновенную сеть.&lt;br /&gt;
&lt;br /&gt;
Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство &amp;lt;tex&amp;gt;\sum\limits_v f(u,v) = 0&amp;lt;/tex&amp;gt; для всех вершин графа. Это равносильно существованию потока между вершинами $s$ и $t$ в сети $G'$, который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит $i$-ое ребро как минимум на $l_i$, что и является необходимым требованием. Если этот поток существует, то будет выполнено:&lt;br /&gt;
* $\sum\limits_v f(u,v)=0,$ где $u \in V'-\{s,t\}, v \in V'$, то есть для всех исходных вершин;&lt;br /&gt;
* В $G': f_i \leqslant c_i - l_i \Rightarrow 0 \leqslant f_i \leqslant c_i - l_i \Rightarrow l_i \leqslant f_i + l_i \leqslant c_i$, что удовлетворяет всем ограничениям.&lt;br /&gt;
Значит, этот поток и есть циркуляция. &lt;br /&gt;
&lt;br /&gt;
Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети $G'$ соответствующие значения минимальной пропускной способности.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
Конструктор ребра принимает следующие аргументы:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{from}&amp;lt;/tex&amp;gt; {{---}} вершина начала ребра&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{to}&amp;lt;/tex&amp;gt; {{---}} вершина конца ребра&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{cap}&amp;lt;/tex&amp;gt; {{---}} минимальная пропускная способность ребра&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{mincap}&amp;lt;/tex&amp;gt; {{---}} максимальная пропускная способность ребра&lt;br /&gt;
 '''function''' circulation(&amp;lt;tex&amp;gt;V,E&amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt;G'= {V,s,t}&amp;lt;/tex&amp;gt;                                      &amp;lt;font color=green&amp;gt;// создаём новый граф с исходными вершинами и добавлением s и t {{---}} исток и сток&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.mincap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.cap - &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.mincap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.minсap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;G' = G' \cup {g,h,k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     maxFlow = getMaxFlow(&amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;)                         &amp;lt;font color=green&amp;gt;// наибольший поток в графе G'&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;e : e\in E'&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from &amp;lt;tex&amp;gt;=s&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &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; &amp;lt; e&amp;lt;/tex&amp;gt;.cap                              &amp;lt;font color=green&amp;gt;// если для текущего ребра flow &amp;lt; cap&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''return''' false&lt;br /&gt;
     '''return''' true&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://dl.dropbox.com/u/39566886/Graph-Theory-Algorithms-M-Ashraf-Iqbal.pdf M. Ashraf Iqbal {{---}}'''Graph Theory and Algorithms''']&lt;br /&gt;
* [http://e-maxx.ru/algo/flow_with_limits MAXimal :: algo :: flow with limits]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Circulation_problem Wikipedia — Circulation problem]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50818</id>
		<title>Теорема о декомпозиции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50818"/>
				<updated>2016-01-07T14:47:58Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Теорема==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
о декомпозиции&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;G = (V, E)&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow_network|транспортная сеть]], &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow|поток]] в &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;O(E)&amp;lt;/tex&amp;gt; путей из истока в сток и циклов: &amp;lt;tex&amp;gt;|f| = \sum\limits_{i=1}^{}c_{i}\cdot f(p_{i}) + \sum\limits_{j=1}^{}d_{j}\cdot f(k_{j})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;p_{i}&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_{j}&amp;lt;/tex&amp;gt; — цикл, &amp;lt;tex&amp;gt;c_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_{j}&amp;lt;/tex&amp;gt; — константы.&lt;br /&gt;
|proof=&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;G&amp;lt;/tex&amp;gt;. Пусть из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; выходит хотя бы одно ребро с положительным потоком. Пойдем по этому ребру, попадем в вершину &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;v_1&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;t&amp;lt;/tex&amp;gt;, иначе по закону сохранения потока для вершины &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt; из нее должно выходить хотя бы одно ребро с положительным потоком в некоторую вершину &amp;lt;tex&amp;gt;v_2&amp;lt;/tex&amp;gt;. Будем продолжать этот процесс до тех пор, пока &amp;lt;tex&amp;gt;v_i&amp;lt;/tex&amp;gt;  не совпадет с &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; (найден путь &amp;lt;tex&amp;gt;p_{i}&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_{j}&amp;lt;/tex&amp;gt;). Данный путь (цикл) будет иметь положительный поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;p_{i}&amp;lt;/tex&amp;gt;) или &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;k_{j}&amp;lt;/tex&amp;gt;), равный минимальному среди потоков по всем ребрам пути (цикла). Уменьшая поток каждого ребра этого пути (цикла) на величину &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;p_{i}&amp;lt;/tex&amp;gt;) или &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;k_{j}&amp;lt;/tex&amp;gt;), получаем новый поток. Будем продолжать описанный алгоритм до тех пор, пока поток из &amp;lt;tex&amp;gt;s&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;G = (V, E)&amp;lt;/tex&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''function''' simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; Q = \varnothing&amp;lt;/tex&amp;gt;                      &amp;lt;font color=green&amp;gt;// множество пройденных рёбер&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt; P = \varnothing &amp;lt;/tex&amp;gt;                      &amp;lt;font color=green&amp;gt;// множество посещённых вершин&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;v = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt; v \notin P &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt; v = t &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         edge &amp;lt;tex&amp;gt;e = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''for''' &amp;lt;tex&amp;gt;u : (v,u) \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt; f(v,u)&amp;gt;0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt;e = (v,u)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 '''break'''&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;e = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''return''' &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; Q&amp;lt;/tex&amp;gt;.push_back(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; P = P \cup \{v\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; v = u &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;v \in P &amp;lt;/tex&amp;gt;                    &amp;lt;font color=green&amp;gt;// нашли цикл, удаляем из &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; все ребра, найденные до того, как &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; была включена в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.begin.from &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop_front()&lt;br /&gt;
     &amp;lt;tex&amp;gt;f(Q) = f(Q)&amp;lt;/tex&amp;gt; - &amp;lt;tex&amp;gt;\min\limits_{(u,v) \in Q}f(u,v) &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;(f, Q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''function''' fullDecomposition():&lt;br /&gt;
     &amp;lt;tex&amp;gt; d = \varnothing &amp;lt;/tex&amp;gt;                       &amp;lt;font color=green&amp;gt;// собственно, декомпозиция графа: совокупность подмножеств, которые являются путями/циклами, и их поток&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)  &amp;lt;font color=green&amp;gt;// один из путей/циклов в графе и его поток&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' (&amp;lt;tex&amp;gt;p \neq \varnothing&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; d = d \cup p &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt; u \in V &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;p \neq \varnothing&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt; d = d \cup \{p\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;d&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;O(VE)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Действительно, каждый путь (цикл) содержит не более &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; вершин, следовательно, поиск пути (цикла) работает за &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;. Т. к. декомпозиция потока содержит &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; путей, то всего в ходе алгоритма при рассмотрении всех вершин будет осуществлено &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; поисков путей (циклов) (в остальных случаях в силу отсутствия потока через вершину поиск пути вызываться не будет). Итого суммарное время работы составит &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
* ''Ravindra Ahuja, Thomas Magnanti, James Orlin'' — '''Network flows''' — Prentice-Hall, Inc. Upper Saddle River, New Jersey, 1993.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке ]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50815</id>
		<title>Циркуляция потока</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50815"/>
				<updated>2016-01-07T14:17:44Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Поток нулевой величины в [[Определение сети, потока|сети]] $G(V, E)$ называется '''циркуляцией''' (англ. ''circulation problem''). Каждое ребро $e_i$ имеет $l_i$ и $c_i$ {{---}} минимальная и максимальная пропускная способности соответственно. Необходимо выяснить, существует ли в этой сети циркуляция, удовлетворяющая пропускным способностям рёбер. &lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Циркул2.png|frame|справа|Рисунок 1. Пример графа и циркуляции в нем (поток/пропуск.способность)]]&lt;br /&gt;
&lt;br /&gt;
Иначе говоря, [[Определение сети, потока#Определение потока|закон сохранения потока]] &amp;lt;tex&amp;gt;\sum\limits_v f(u,v)=0&amp;lt;/tex&amp;gt; должен выполняться для '''всех''' вершин графа, а значит нет нужды в истоке и стоке. Когда все  $l_i$ равны $0$, достаточно пустить поток нулевой величины из каждой вершины, что и будет ответом. Поэтому далее в графе будут существовать ребра с положительно нижней пропускной способностью.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Решение==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;Для решения этой задачи заменим исходную сеть $G$ на $G'$ следующим образом. Сначала добавим в граф вершины $s$ {{---}} исток и $t$ {{---}} сток. Для каждого ребра $e_i = v_{from} \xrightarrow{l_i, c_i} v_{to}$ добавим ребра $s \xrightarrow{0, l_i} v_{to}$ и $u_{from} \xrightarrow{0, l_i} t$, а также сделаем в ребре $e_i$ изменения: $c_i = c_i - l_i, l_i = 0$ (см. рисунок 2).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Циркуляция.png|frame|center|Рисунок 2. Слева - изначальный граф. Для каждого ребра заданы его нижняя и верхняя пропускные способности. Справа - граф после преобразований ребер.]]&lt;br /&gt;
&lt;br /&gt;
Каждое ребро изначального графа заменяется на три новых. Если по ребру $e_i = (v_{from}, v_{to})$ в исходной сети протекает поток $l_i \leqslant f_i \leqslant c_i$, то в новой сети по ребру $(s, v_{to})$ должен течь поток, равный $l_i$, то есть его пропускной способности. Поток, который вытекает из $v_{from}$ по ребру в $G$, заменяется на поток, который протекает по ребрам $(v_{from}, v_{to})$ и $(v_{from}, t)$ (поскольку сумма их пропускных способностей в полученном графе равна $c_i$). Аналогично, для вершины $v_{to}$ суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети $G'$ все $l_i = 0$, то есть мы имеем обыкновенную сеть.&lt;br /&gt;
&lt;br /&gt;
Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство &amp;lt;tex&amp;gt;\sum\limits_v f(u,v) = 0&amp;lt;/tex&amp;gt; для всех вершин графа. Это равносильно существованию потока между вершинами $s$ и $t$ в сети $G'$, который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит $i$-ое ребро как минимум на $l_i$, что и является необходимым требованием. Если этот поток существует, то будет выполнено:&lt;br /&gt;
* $\sum\limits_v f(u,v)=0,$ где $u \in V'-\{s,t\}, v \in V'$, то есть для всех исходных вершин;&lt;br /&gt;
* В $G': f_i \leqslant c_i - l_i \Rightarrow 0 \leqslant f_i \leqslant c_i - l_i \Rightarrow l_i \leqslant f_i + l_i \leqslant c_i$, что удовлетворяет всем ограничениям.&lt;br /&gt;
Значит, этот поток и есть циркуляция. &lt;br /&gt;
&lt;br /&gt;
Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети $G'$ соответствующие значения минимальной пропускной способности.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''function''' circulation(&amp;lt;tex&amp;gt;V,E&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     &amp;lt;tex&amp;gt;G=\varnothing&amp;lt;/tex&amp;gt;                                               &amp;lt;font color=green&amp;gt;// пустой граф, вершины s и t - исток и сток&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt;                                        &amp;lt;font color=green&amp;gt;// конструктор ребра принимает 4 параметра: две инцидентные ребру вершины, величину потока через это ребро и пропускную способность&amp;lt;/font&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.cap - &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; = Edge(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
         &amp;lt;tex&amp;gt;G = G \cup {t,g,h}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     maxFlow = getMaxFlow(&amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;)                             &amp;lt;font color=green&amp;gt;// наибольший поток в графе G&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from &amp;lt;tex&amp;gt;=s&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &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; &amp;lt; e&amp;lt;/tex&amp;gt;.cap                                  &amp;lt;font color=green&amp;gt;// если для текущего ребра flow &amp;lt; cap&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''return''' false&lt;br /&gt;
     '''return''' true&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://dl.dropbox.com/u/39566886/Graph-Theory-Algorithms-M-Ashraf-Iqbal.pdf M. Ashraf Iqbal {{---}}'''Graph Theory and Algorithms''']&lt;br /&gt;
* [http://e-maxx.ru/algo/flow_with_limits MAXimal :: algo :: flow with limits]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Circulation_problem Wikipedia — Circulation problem]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50814</id>
		<title>Теорема о декомпозиции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50814"/>
				<updated>2016-01-07T13:53:40Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Теорема==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
о декомпозиции&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;G = (V, E)&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow_network|транспортная сеть]], &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow|поток]] в &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;O(E)&amp;lt;/tex&amp;gt; путей из истока в сток и циклов: &amp;lt;tex&amp;gt;|f| = \sum\limits_{i=1}^{}c_{i}\cdot f(p_{i}) + \sum\limits_{j=1}^{}d_{j}\cdot f(k_{j})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;p_{i}&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_{j}&amp;lt;/tex&amp;gt; — цикл, &amp;lt;tex&amp;gt;c_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_{j}&amp;lt;/tex&amp;gt; — константы.&lt;br /&gt;
|proof=&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;G&amp;lt;/tex&amp;gt;. Пусть из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; выходит хотя бы одно ребро с положительным потоком. Пойдем по этому ребру, попадем в вершину &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;v_1&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;t&amp;lt;/tex&amp;gt;, иначе по закону сохранения потока для вершины &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt; из нее должно выходить хотя бы одно ребро с положительным потоком в некоторую вершину &amp;lt;tex&amp;gt;v_2&amp;lt;/tex&amp;gt;. Будем продолжать этот процесс до тех пор, пока &amp;lt;tex&amp;gt;v_i&amp;lt;/tex&amp;gt;  не совпадет с &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; (найден путь &amp;lt;tex&amp;gt;p_{i}&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_{j}&amp;lt;/tex&amp;gt;). Данный путь (цикл) будет иметь положительный поток &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;p_{i}&amp;lt;/tex&amp;gt;) или &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;k_{j}&amp;lt;/tex&amp;gt;), равный минимальному среди потоков по всем ребрам пути (цикла). Уменьшая поток каждого ребра этого пути (цикла) на величину &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;p_{i}&amp;lt;/tex&amp;gt;) или &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;k_{j}&amp;lt;/tex&amp;gt;), получаем новый поток. Будем продолжать описанный алгоритм до тех пор, пока поток из &amp;lt;tex&amp;gt;s&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;G = (V, E)&amp;lt;/tex&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''function''' simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     &amp;lt;tex&amp;gt; Q = \varnothing&amp;lt;/tex&amp;gt;                      &amp;lt;font color=green&amp;gt;// множество пройденных рёбер&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt; P = \varnothing &amp;lt;/tex&amp;gt;                      &amp;lt;font color=green&amp;gt;// множество посещённых вершин&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;v = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt; v \notin P &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt; v = t &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         edge &amp;lt;tex&amp;gt;e = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''for''' &amp;lt;tex&amp;gt;u : (v,u) \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt; f(v,u)&amp;gt;0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt;e = (v,u)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 '''break'''&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;e = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''return''' &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; Q&amp;lt;/tex&amp;gt;.push_back(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; P = P \cup \{v\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; v = u &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;v \in P &amp;lt;/tex&amp;gt;                    &amp;lt;font color=green&amp;gt;// нашли цикл, удаляем из &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; все ребра, найденные до того, как &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; была включена в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.begin.from &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop_front()&lt;br /&gt;
     &amp;lt;tex&amp;gt;f(Q) = f(Q)&amp;lt;/tex&amp;gt; - &amp;lt;tex&amp;gt;\min\limits_{(u,v) \in Q}f(u,v) &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;(f, Q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''function''' fullDecomposition()&lt;br /&gt;
     &amp;lt;tex&amp;gt; d = \varnothing &amp;lt;/tex&amp;gt;                       &amp;lt;font color=green&amp;gt;// собственно, декомпозиция графа: совокупность подмножеств, которые являются путями/циклами, и их поток&amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)  &amp;lt;font color=green&amp;gt;// один из путей/циклов в графе и его поток&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' (&amp;lt;tex&amp;gt;p \neq \varnothing&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; d = d \cup p &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt; u \in V &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;p \neq \varnothing&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt; d = d \cup \{p\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;d&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;O(VE)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Действительно, каждый путь (цикл) содержит не более &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; вершин, следовательно, поиск пути (цикла) работает за &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;. Т. к. декомпозиция потока содержит &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; путей, то всего в ходе алгоритма при рассмотрении всех вершин будет осуществлено &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; поисков путей (циклов) (в остальных случаях в силу отсутствия потока через вершину поиск пути вызываться не будет). Итого суммарное время работы составит &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
* ''Ravindra Ahuja, Thomas Magnanti, James Orlin'' — '''Network flows''' — Prentice-Hall, Inc. Upper Saddle River, New Jersey, 1993.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке ]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B3%D1%80%D0%B0%D1%84%D0%B0&amp;diff=50813</id>
		<title>Двойственный граф планарного графа</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B3%D1%80%D0%B0%D1%84%D0%B0&amp;diff=50813"/>
				<updated>2016-01-07T13:09:25Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|definition=Граф&amp;lt;ref&amp;gt;На самом деле, ''двойственный граф'' — '''псевдограф''', поскольку в нём могут быть петли и кратные рёбра.&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; называется '''двойственным''' (англ. ''dual graph'') к [[Укладка графа на плоскости|планарному графу]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, если:&lt;br /&gt;
# Вершины &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; соответствуют граням &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Между двумя вершинами в &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; есть ребро тогда и только тогда, когда соответствующие грани в &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; имеют общее ребро.&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Dual_graph_2.png|180px|thumb|right|Граф (белые вершины) и двойственный ему (серые вершины).]]&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Чтобы для данного плоского графа &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; построить двойственный &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;, необходимо поместить по вершине &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; в каждую грань &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; (включая внешнюю), а затем, если две грани в &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; имеют общее ребро, соединить ребром соответствующие им вершины в &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; (если грани имеют несколько общих рёбер, соответствующие вершины следует соединить несколькими параллельными рёбрами). В результате всегда получится плоский псевдограф.&lt;br /&gt;
&lt;br /&gt;
Например, существуют графы, двойственные себе: — &amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt;. Далее мы убедимся, что среди полных графов только они обладают таким свойством.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
[[Файл:Treenflower new.png|250px|thumb|right|Дерево и двойственный к нему «цветок».‎]]&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; — ''двойственный'' к двусвязному графу &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; — ''двойственный'' к &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* У одного и того же графа может быть несколько ''двойственных'', в зависимости от конкретной укладки (см. картинку).&lt;br /&gt;
* Поскольку любой трёхсвязный планарный граф допускает только одну укладку на сфере&amp;lt;ref&amp;gt;Харари, Ф. Теория графов. — М.: Книжный дом «ЛИБРОКОМ», 2009. — Теорема 11.5 — С. 130. — ISBN 978­-5­-397­-00622­-4&amp;lt;/ref&amp;gt;, у него должен быть единственный ''двойственный граф''.&lt;br /&gt;
* [[Мост, эквивалентные определения|Мост]] переходит в петлю, а петля — в мост. Частный случай: полный граф &amp;lt;tex&amp;gt;K_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Мультиграф, ''двойственный'' к дереву, — цветок.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Самодвойственные графы ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Планарный граф называется '''самодвойственным''' (англ. ''self-dual graph''), если он изоморфен своему двойственному графу.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[Файл:Wheel8_new2.png|500px|thumb|left|Колесо и двойственный ему граф {{---}} тоже колесо.]]&lt;br /&gt;
 |[[Файл:K4_new.png|250px|thumb|right|&amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; (он же колесо).]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; — самодвойственные графы. Среди полных графов других самодвойственных нет.&lt;br /&gt;
|proof=Проверить, что &amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; полны и самодвойственны несложно. Докажем, что других нет.&amp;lt;br/&amp;gt;Поскольку грани графа переходят в вершины, количество вершин и граней в исходном графе должно совпадать, т.е. &amp;lt;tex&amp;gt;V = F&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Подставив в [[Формула Эйлера|формулу Эйлера]] имеем: &amp;lt;tex&amp;gt;2V = E + 2 \Leftrightarrow V = \dfrac{E}{2} + 1&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;В полном графе &amp;lt;tex&amp;gt;E = \dfrac{V \cdot (V - 1)}{2}&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Получаем квадратное уравнение: &amp;lt;tex&amp;gt;V^2 - 5V + 4 = 0&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Его решения: &amp;lt;tex&amp;gt;V_1 = 1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;V_2 = 4&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Таким образом, чтобы ''полный'' граф был ''самодвойственным'', в нём должна быть ровно '''одна''' или '''четыре''' вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style='clear: both;'&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|statement=Все колёса самодвойственны.&lt;br /&gt;
|proof=Это утверждение очевидно.&amp;lt;br/&amp;gt;Достаточно убедиться, что два варианта укладки колеса (вершина с большой степенью внутри или вершина с большой степенью снаружи) двойственны друг другу.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&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;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации==&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84 Википедия — Двойственный граф]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%9F%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84 Википедия — Планарный граф]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B3%D1%80%D0%B0%D1%84%D0%B0&amp;diff=50325</id>
		<title>Двойственный граф планарного графа</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B3%D1%80%D0%B0%D1%84%D0%B0&amp;diff=50325"/>
				<updated>2015-12-20T17:46:28Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|definition=Граф&amp;lt;ref&amp;gt;На самом деле, ''двойственный граф'' — '''псевдограф''', поскольку в нём могут быть петли и кратные рёбра.&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; называется '''двойственным''' (англ. ''dual graph'') к [[Укладка графа на плоскости|планарному графу]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, если:&lt;br /&gt;
# Вершины &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; соответствуют граням &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Между двумя вершинами в &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; есть ребро тогда и только тогда, когда соответствующие грани в &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; имеют общее ребро.&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Dual_graph_2.png|180px|thumb|right|Граф (белые вершины) и двойственный ему (серые вершины).]]&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Чтобы для данного плоского графа &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; построить двойственный &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;, необходимо поместить по вершине &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; в каждую грань &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; (включая внешнюю), а затем, если две грани в &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; имеют общее ребро, соединить ребром соответствующие им вершины в &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; (если грани имеют несколько общих рёбер, соответствующие вершины следует соединить несколькими параллельными рёбрами). В результате всегда получится плоский псевдограф.&lt;br /&gt;
&lt;br /&gt;
Например: тетраэдр — самодвойственный граф, куб и октаэдр — двойственные, так же как додекаэдр и икосаэдр. Эти пять графов, образованные вершинами и рёбрами правильных многогранников, называют ''платоновыми''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
[[Файл:Treenflower new.png|250px|thumb|right|Дерево и двойственный к нему «цветок».‎]]&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; — ''двойственный'' к двусвязному графу &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; — ''двойственный'' к &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* У одного и того же графа может быть несколько ''двойственных'', в зависимости от конкретной укладки (см. картинку).&lt;br /&gt;
* Поскольку любой трёхсвязный планарный граф допускает только одну укладку на сфере&amp;lt;ref&amp;gt;Харари, Ф. Теория графов. — М.: Книжный дом «ЛИБРОКОМ», 2009. — Теорема 11.5 — С. 130. — ISBN 978­-5­-397­-00622­-4&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;
|definition=Планарный граф называется '''самодвойственным''' (англ. ''self-dual graph''), если он изоморфен своему двойственному графу.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[Файл:Wheel8_new2.png|500px|thumb|left|Колесо и двойственный ему граф {{---}} тоже колесо.]]&lt;br /&gt;
 |[[Файл:K4_new.png|250px|thumb|right|&amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; (он же колесо).]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; — самодвойственные графы. Среди полных графов других самодвойственных нет.&lt;br /&gt;
|proof=Проверить, что &amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; полны и самодвойственны несложно. Докажем, что других нет.&amp;lt;br/&amp;gt;Поскольку грани графа переходят в вершины, количество вершин и граней в исходном графе должно совпадать, т.е. &amp;lt;tex&amp;gt;V = F&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Подставив в [[Формула Эйлера|формулу Эйлера]] имеем: &amp;lt;tex&amp;gt;2V = E + 2 \Leftrightarrow V = \dfrac{E}{2} + 1&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;В полном графе &amp;lt;tex&amp;gt;E = \dfrac{V \cdot (V - 1)}{2}&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Получаем квадратное уравнение: &amp;lt;tex&amp;gt;V^2 - 5V + 4 = 0&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Его решения: &amp;lt;tex&amp;gt;V_1 = 1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;V_2 = 4&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Таким образом, чтобы ''полный'' граф был ''самодвойственным'', в нём должна быть ровно '''одна''' или '''четыре''' вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style='clear: both;'&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|statement=Все колёса самодвойственны.&lt;br /&gt;
|proof=Это утверждение очевидно.&amp;lt;br/&amp;gt;Достаточно убедиться, что два варианта укладки колеса (вершина с большой степенью внутри или вершина с большой степенью снаружи) двойственны друг другу.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&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;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации==&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84 Википедия — Двойственный граф]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%9F%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84 Википедия — Планарный граф]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%BF%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D1%8F_%D0%AD%D0%B9%D0%BB%D0%B5%D1%80%D0%BE%D0%B2%D0%B0_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0&amp;diff=50312</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%BF%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D1%8F_%D0%AD%D0%B9%D0%BB%D0%B5%D1%80%D0%BE%D0%B2%D0%B0_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0&amp;diff=50312"/>
				<updated>2015-12-20T04:58:53Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Алгоритм ==&lt;br /&gt;
=== Описание алгоритма ===&lt;br /&gt;
Алгоритм находит [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов|Эйлеров цикл]] как в [[Ориентированный граф|ориентированном]], так и в [[Основные определения теории графов#Неориентированные графы|неориентированном графе]]. Перед запуском алгоритма необходимо [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов|проверить граф на эйлеровость]]. Чтобы построить [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов|Эйлеров путь]], нужно запустить алгоритм из вершины с нечетной степенью.&amp;lt;br&amp;gt;&lt;br /&gt;
Алгоритм напоминает поиск в ширину. Главное отличие состоит в том, что пройденными помечаются не вершины, а ребра графа. Начиная со стартовой вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; строим путь, добавляя на каждом шаге не пройденное еще ребро, смежное с текущей вершиной. Вершины пути накапливаются в [[Стек | стеке]] &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда наступает такой момент, что для текущей вершины &amp;lt;tex&amp;gt;w&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;
&amp;lt;font size=2&amp;gt;&lt;br /&gt;
'''Код проверки графа на эйлеровость:'''&lt;br /&gt;
 '''boolean''' checkForEulerPath():&lt;br /&gt;
    '''int''' OddVertex &amp;lt;tex&amp;gt;= 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) '''mod''' &amp;lt;tex&amp;gt;2 == 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
            OddVertex++&lt;br /&gt;
    '''if''' OddVertex &amp;lt;tex&amp;gt; &amp;gt; 2 &amp;lt;/tex&amp;gt;&amp;lt;font color=darkgreen&amp;gt;// если количество вершин с нечетной степенью больше двух, то граф не является эйлеровым&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''return''' ''false''&lt;br /&gt;
    '''boolean''' visited(&amp;lt;tex&amp;gt;|V|&amp;lt;/tex&amp;gt;, ''false'') &amp;lt;font color=darkgreen&amp;gt;// массив инициализируется значениями ''false''&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt; &amp;gt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
            dfs(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, visited)&lt;br /&gt;
            '''break'''&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt; &amp;gt; 0&amp;lt;/tex&amp;gt; '''and''' '''not''' visited[&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;]   &amp;lt;font color=darkgreen&amp;gt;// если количество компонент связности, содержащие ребра, больше одной,&amp;lt;/font&amp;gt;&lt;br /&gt;
            '''return''' ''false''             &amp;lt;font color=darkgreen&amp;gt; // то граф не является эйлеровым&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''return''' ''true''   &amp;lt;font color=darkgreen&amp;gt;// граф является эйлеровым&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Код построения эйлерова пути:'''&lt;br /&gt;
 '''function''' findEulerPath(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;):  &amp;lt;font color=darkgreen&amp;gt; // если граф является полуэйлеровым, то алгоритм следует запускать из вершины нечетной степени &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;) '''mod''' &amp;lt;tex&amp;gt;2 == 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;v = u&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''break'''&lt;br /&gt;
    Stack &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
    '''while not''' &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.empty()&lt;br /&gt;
        &amp;lt;tex&amp;gt;w = &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.top()&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''if''' (&amp;lt;tex&amp;gt;w, u&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;\in E&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt; // нашли ребро, по которому ещё не прошли&amp;lt;/font&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;) &amp;lt;font color=darkgreen&amp;gt; // добавили новую вершину в стек&amp;lt;/font&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;w, u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
                '''break'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt; w == S&amp;lt;/tex&amp;gt;.top()&lt;br /&gt;
            &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.pop() &amp;lt;font color=darkgreen&amp;gt; // не нашлось инцидентных вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; рёбер, по которым ещё не прошли&amp;lt;/font&amp;gt;&lt;br /&gt;
            print(&amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&amp;lt;/font&amp;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;, и он не мог стать пустым. Значит алгоритм пройдёт по всем рёбрам хотя бы один раз.&lt;br /&gt;
Но так как после прохода по ребру оно удаляется, то пройти по нему дважды алгоритм не может.&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, с которой начат обход графа, будет последней помещена в путь &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Так как изначально стек пуст, и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; входит в стек первой, то после прохода по инцидентным ребрам, алгоритм возвращается к данной вершине, выводит ее и опустошает стек, затем выполнение программы завершается.&amp;lt;br&amp;gt;&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=Напечатанный путь &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} корректный маршрут в графе, в котором каждые две соседние вершины &amp;lt;tex&amp;gt;u_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i+1}&amp;lt;/tex&amp;gt; будут образовывать ребро &amp;lt;tex&amp;gt;(u_i, u_{i+1}) \in E&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=Будем говорить, что ребро &amp;lt;tex&amp;gt;(w,u)&amp;lt;/tex&amp;gt; представлено в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, если в какой-то момент работы алгоритма вершины &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u&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;P&amp;lt;/tex&amp;gt; перемещена вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, а следующей в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; лежит &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;. Возможны 2 варианта:&lt;br /&gt;
*На следующем шаге для вершины &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; не найдётся инцидентного ребра, тогда &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; переместят в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, и ребро &amp;lt;tex&amp;gt;(w,u)&amp;lt;/tex&amp;gt; будет представлено в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Иначе будет пройдена некоторая последовательность ребер &amp;lt;tex&amp;gt;{u_1, u_2, ..., u_k}&amp;lt;/tex&amp;gt;, начинающаяся в вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; и проходящая по ребру &amp;lt;tex&amp;gt;(w, u_1)&amp;lt;/tex&amp;gt;. Докажем, что данный проход &amp;lt;tex&amp;gt;{u_1, u_2, ..., u_k}&amp;lt;/tex&amp;gt; закончится в вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;:&lt;br /&gt;
#Ребро &amp;lt;tex&amp;gt;(u_{k-1}, u_k)&amp;lt;/tex&amp;gt; не может быть инцидентно вершинам &amp;lt;tex&amp;gt;u_1, \dots , u_{k-2}&amp;lt;/tex&amp;gt;, иначе степень вершины &amp;lt;tex&amp;gt;u_k&amp;lt;/tex&amp;gt; окажется нечетной.&lt;br /&gt;
#Предположим, что &amp;lt;tex&amp;gt;(u_{k-1}, u_k)&amp;lt;/tex&amp;gt; инцидентно вершине, пройденной при обходе графа из вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. Но это неверно, так как тогда бы данные вершины пройдены ранее.&lt;br /&gt;
Из этого следует, что мы закончим обход в вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;. Следовательно, данная вершина первой поместится в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; вслед за &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, и ребро &amp;lt;tex&amp;gt;(w, u)&amp;lt;/tex&amp;gt; будет представлено в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=proof1&lt;br /&gt;
|statement=Данный алгоритм находит корректный эйлеров путь.&lt;br /&gt;
|proof=Из предыдущих лемм следует, что &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} искомый эйлеров путь и алгоритм работает корректно.&lt;br /&gt;
}}&lt;br /&gt;
=== Рекурсивная реализация ===&lt;br /&gt;
&amp;lt;font size=2&amp;gt;&lt;br /&gt;
 '''function''' findEulerPath(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; : Vertex):&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;(v,u)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
        remove &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findEulerPath(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
    print(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Если реализовать поиск ребер инцидентных вершине и удаление ребер за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, то алгоритм будет работать за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы реализовать поиск за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, для хранения графа следует использовать списки смежных вершин; для удаления достаточно добавить всем ребрам свойство &amp;lt;tex&amp;gt;\mathtt{deleted}&amp;lt;/tex&amp;gt; бинарного типа.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
* [[Покрытие ребер графа путями]]&lt;br /&gt;
* [[Произвольно вычерчиваемые из заданной вершины графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Эйлеров_цикл Википедия {{---}} Эйлеров цикл]&lt;br /&gt;
* [http://e-maxx.ru/algo/euler_path  Статья про нахождение Эйлерова пути с реализацией на С++ на сайте e-maxx.ru]&lt;br /&gt;
* [http://ивтб.рф/exams/саод/36.htm  Статья про нахождение Эйлерова пути с реализацией на Pascal на сайте ивтб.рф]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Обходы графов]]&lt;br /&gt;
[[Категория: Эйлеровы графы]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%BF%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D1%8F_%D0%AD%D0%B9%D0%BB%D0%B5%D1%80%D0%BE%D0%B2%D0%B0_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0&amp;diff=50142</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%BF%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D1%8F_%D0%AD%D0%B9%D0%BB%D0%B5%D1%80%D0%BE%D0%B2%D0%B0_%D1%86%D0%B8%D0%BA%D0%BB%D0%B0&amp;diff=50142"/>
				<updated>2015-12-06T07:35:05Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Алгоритм ==&lt;br /&gt;
=== Описание алгоритма ===&lt;br /&gt;
Алгоритм находит [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов|Эйлеров цикл]] как в [[Ориентированный граф|ориентированном]], так и в [[Основные определения теории графов#Неориентированные графы|неориентированном графе]]. Перед запуском алгоритма необходимо [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов|проверить граф на эйлеровость]]. Чтобы построить [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов|Эйлеров путь]], нужно запустить алгоритм из вершины с нечетной степенью.&amp;lt;br&amp;gt;&lt;br /&gt;
Алгоритм напоминает поиск в ширину. Главное отличие состоит в том, что пройденными помечаются не вершины, а ребра графа. Начиная со стартовой вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; строим путь, добавляя на каждом шаге не пройденное еще ребро, смежное с текущей вершиной. Вершины пути накапливаются в [[Стек | стеке]] &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда наступает такой момент, что для текущей вершины &amp;lt;tex&amp;gt;w&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;
&amp;lt;font size=2&amp;gt;&lt;br /&gt;
'''Код проверки графа на эйлеровость:'''&lt;br /&gt;
 '''boolean''' checkForEulerPath():&lt;br /&gt;
    '''int''' OddVertex &amp;lt;tex&amp;gt;= 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) '''mod''' &amp;lt;tex&amp;gt;2 == 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
            OddVertex++&lt;br /&gt;
    '''if''' OddVertex &amp;lt;tex&amp;gt; &amp;gt; 2 &amp;lt;/tex&amp;gt;&amp;lt;font color=darkgreen&amp;gt;// если количество вершин с нечетной степенью больше двух, то граф не является эйлеровым&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''return''' ''false''&lt;br /&gt;
    '''boolean''' visited(&amp;lt;tex&amp;gt;|V|&amp;lt;/tex&amp;gt;, ''false'') &amp;lt;font color=darkgreen&amp;gt;// массив инициализируется значениями ''false''&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt; &amp;gt; 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
            dfs(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, visited)&lt;br /&gt;
            '''break'''&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt; &amp;gt; 0&amp;lt;/tex&amp;gt; '''and''' '''not''' visited[&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;]   &amp;lt;font color=darkgreen&amp;gt;// если количество компонент связности, содержащие ребра, больше одной,&amp;lt;/font&amp;gt;&lt;br /&gt;
            '''return''' ''false''             &amp;lt;font color=darkgreen&amp;gt; // то граф не является эйлеровым&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''return''' ''true''   &amp;lt;font color=darkgreen&amp;gt;// граф является эйлеровым&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Код построения эйлерова пути:'''&lt;br /&gt;
 '''function''' findEulerPath(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;):  &amp;lt;font color=darkgreen&amp;gt; // если граф является полуэйлеровым, то алгоритм следует запускать из вершины нечетной степени &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;\operatorname{deg}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;) '''mod''' &amp;lt;tex&amp;gt;2 == 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;v = u&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''break'''&lt;br /&gt;
    Stack &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
    '''while not''' &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.empty()&lt;br /&gt;
        &amp;lt;tex&amp;gt;w = &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.top()&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''if''' (&amp;lt;tex&amp;gt;w, u&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;\in E&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt; // нашли ребро, по которому ещё не прошли&amp;lt;/font&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;) &amp;lt;font color=darkgreen&amp;gt; // добавили новую вершину в стек&amp;lt;/font&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;w, u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
                '''break'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt; w == S&amp;lt;/tex&amp;gt;.top()&lt;br /&gt;
            &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.pop() &amp;lt;font color=darkgreen&amp;gt; // не нашлось инцидентных вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; рёбер, по которым ещё не прошли&amp;lt;/font&amp;gt;&lt;br /&gt;
            print(&amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=proof1&lt;br /&gt;
|statement=Данный алгоритм находит корректный эйлеров путь.&lt;br /&gt;
|proof=&lt;br /&gt;
{{TODO | t = Довести до ума}}&amp;lt;br&amp;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;br&amp;gt;&lt;br /&gt;
Вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, с которой начат обход графа, будет последней помещена в путь &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Так как изначально стек пуст, и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; входит в стек первой, то после прохода по инцидентным ребрам, алгоритм возвращается к данной вершине, выводит ее и опустошает стек, затем выполнение программы завершается.&amp;lt;br&amp;gt;&lt;br /&gt;
Напечатанный путь &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} корректный маршрут в графе, в котором каждые две соседние вершины &amp;lt;tex&amp;gt;u_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i+1}&amp;lt;/tex&amp;gt; будут образовывать ребро &amp;lt;tex&amp;gt;(u_i, u_{i+1})&amp;lt;/tex&amp;gt;, принадлежащее &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;. Будем говорить, что ребро &amp;lt;tex&amp;gt;(w,u)&amp;lt;/tex&amp;gt; представлено в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, если в какой-то момент работы алгоритма вершины &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u&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;P&amp;lt;/tex&amp;gt; перемещена вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, а следующей в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; лежит &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;. Возможны 2 варианта:&lt;br /&gt;
#На следующем шаге &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; перемещена в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;(w,u)&amp;lt;/tex&amp;gt; представлено в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Сначала будет пройдена некоторая последовательность ребер, начинающаяся в вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;, и проходящая по ребру &amp;lt;tex&amp;gt;(w, u_1)&amp;lt;/tex&amp;gt;. Докажем, что данный проход &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;{u_1, u_2, ..., u_k}&amp;lt;/tex&amp;gt; закончится в вершине &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;: ребро &amp;lt;tex&amp;gt;(u_{k-1}, u_k)&amp;lt;/tex&amp;gt; не может быть инцидентно вершинам &amp;lt;tex&amp;gt;u_1, \dots , u_{k-2}&amp;lt;/tex&amp;gt;. Иначе степень вершины &amp;lt;tex&amp;gt;u_k&amp;lt;/tex&amp;gt; будет нечетной. Предположим, что &amp;lt;tex&amp;gt;(u_{k-1}, u_k)&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;. Следовательно, данная вершина первой поместится в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; вслед за &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, и ребро &amp;lt;tex&amp;gt;(w, u)&amp;lt;/tex&amp;gt; будет представлено в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Из этого следует, что &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} искомый эйлеров путь.&lt;br /&gt;
}}&lt;br /&gt;
=== Рекурсивная реализация ===&lt;br /&gt;
&amp;lt;font size=2&amp;gt;&lt;br /&gt;
 '''function''' findEulerPath(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; : Vertex):&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;(v,u)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt;&lt;br /&gt;
        remove &amp;lt;tex&amp;gt;(v, u)&amp;lt;/tex&amp;gt;&lt;br /&gt;
        findEulerPath(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
    print(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Если реализовать поиск ребер инцидентных вершине и удаление ребер за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, то алгоритм будет работать за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы реализовать поиск за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, для хранения графа следует использовать списки смежных вершин; для удаления достаточно добавить всем ребрам свойство &amp;lt;tex&amp;gt;\mathtt{deleted}&amp;lt;/tex&amp;gt; бинарного типа.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
* [[Покрытие ребер графа путями]]&lt;br /&gt;
* [[Произвольно вычерчиваемые из заданной вершины графы]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Эйлеров_цикл Википедия {{---}} Эйлеров цикл]&lt;br /&gt;
* [http://e-maxx.ru/algo/euler_path  Статья про нахождение Эйлерова пути с реализацией на С++ на сайте e-maxx.ru]&lt;br /&gt;
* [http://ивтб.рф/exams/саод/36.htm  Статья про нахождение Эйлерова пути с реализацией на Pascal на сайте ивтб.рф]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Обходы графов]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50041</id>
		<title>Циркуляция потока</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50041"/>
				<updated>2015-11-29T14:48:32Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;==Определение задачи==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Поток нулевой величины в [[Определение сети, потока|сети]] $G(V, E)$ называется '''циркуляцией''' (англ. ''circulation problem''). Каждое ребро $e_i$ имеет $l_i$ и $c_i$ {{---}} минимальная и максимальная пропускная способности соответственно. Необходимо выяснить, существует ли в этой сети циркуляция, удовлетворяющая пропускным способностям рёбер. &lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Циркул2.png|frame|справа|Рисунок 1. Пример графа и циркуляции в нем (поток/пропуск.способность)]]&lt;br /&gt;
&lt;br /&gt;
Иначе говоря, [[Определение сети, потока#Определение потока|закон сохранения потока]] &amp;lt;tex&amp;gt;\sum\limits_v f(u,v)=0&amp;lt;/tex&amp;gt; должен выполняться для '''всех''' вершин графа, а значит нет нужды в истоке и стоке. Когда все  $l_i$ равны $0$, достаточно пустить поток нулевой величины из каждой вершины, что и будет ответом. Поэтому далее в графе будут существовать ребра с положительно нижней пропускной способностью. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Решение==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;Для решения этой задачи заменим исходную сеть $G$ на $G'$ следующим образом. Сначала добавим в граф вершины $s$ {{---}} исток и $t$ {{---}} сток. Для каждого ребра $e_i = v_{from} \xrightarrow{l_i, c_i} v_{to}$ добавим ребра $s \xrightarrow{0, l_i} v_{to}$ и $u_{from} \xrightarrow{0, l_i} t$, а также сделаем в ребре $e_i$ изменения: $c_i = c_i - l_i, l_i = 0$ (см. рисунок 2).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Циркуляция.png|frame|center|Рисунок 2. Слева - изначальный граф. Для каждого ребра заданы его нижняя и верхняя пропускные способности. Справа - граф после преобразований ребер.]]&lt;br /&gt;
&lt;br /&gt;
Каждое ребро изначального графа заменяется на три новых. Если по ребру $e_i = (v_{from}, v_{to})$ в исходной сети протекает поток $l_i \leqslant f_i \leqslant c_i$, то в новой сети по ребру $(s, v_{to})$ должен течь поток, равный $l_i$, то есть его пропускной способности. Поток, который вытекает из $v_{from}$ по ребру в $G$, заменяется на поток, который протекает по ребрам $(v_{from}, v_{to})$ и $(v_{from}, t)$ (поскольку сумма их пропускных способностей в полученном графе равна $c_i$). Аналогично, для вершины $v_{to}$ суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети $G'$ все $l_i = 0$, то есть мы имеем обыкновенную сеть.&lt;br /&gt;
&lt;br /&gt;
Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство &amp;lt;tex&amp;gt;\sum\limits_v f(u,v) = 0&amp;lt;/tex&amp;gt; для всех вершин графа. Это равносильно существованию потока между вершинами $s$ и $t$ в сети $G'$, который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит $i$-ое ребро как минимум на $l_i$, что и является необходимым требованием. Если этот поток существует, то будет выполнено:&lt;br /&gt;
* $\sum\limits_v f(u,v)=0,$ где $u \in V'-\{s,t\}, v \in V'$, то есть для всех исходных вершин;&lt;br /&gt;
* В $G': f_i \leqslant c_i - l_i \Rightarrow 0 \leqslant f_i \leqslant c_i - l_i \Rightarrow l_i \leqslant f_i + l_i \leqslant c_i$, что удовлетворяет всем ограничениям.&lt;br /&gt;
Значит, этот поток и есть циркуляция. &lt;br /&gt;
&lt;br /&gt;
Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети $G'$ соответствующие значения минимальной пропускной способности.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;tex&amp;gt;G=\varnothing&amp;lt;/tex&amp;gt;                                           &amp;lt;font color=green&amp;gt;// пустой граф, вершины 0 и n + 1 - исток и сток, в исходном графе n вершин и m рёбер&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt;                                       &amp;lt;font color=green&amp;gt;// ребро с полями (from, to, min_cap, cap)&amp;lt;/font&amp;gt;&lt;br /&gt;
     edge &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
     edge &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.cap &amp;lt;tex&amp;gt;-e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
     edge &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;n+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
     &amp;lt;tex&amp;gt;G = G \cup {t,g,h}&amp;lt;/tex&amp;gt;&lt;br /&gt;
 max_flow = getmaxflow(&amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;)                         &amp;lt;font color=green&amp;gt;// наибольший поток в графе G&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from &amp;lt;tex&amp;gt;=s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &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;&amp;lt; e&amp;lt;/tex&amp;gt;.cap                               &amp;lt;font color=green&amp;gt;// если для текущего ребра flow &amp;lt; cap&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''return''' false&lt;br /&gt;
 '''return''' true&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://dl.dropbox.com/u/39566886/Graph-Theory-Algorithms-M-Ashraf-Iqbal.pdf M. Ashraf Iqbal {{---}}'''Graph Theory and Algorithms''']&lt;br /&gt;
* [http://e-maxx.ru/algo/flow_with_limits MAXimal :: algo :: flow with limits]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Circulation_problem Wikipedia — Circulation problem]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50036</id>
		<title>Циркуляция потока</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B8%D1%80%D0%BA%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0&amp;diff=50036"/>
				<updated>2015-11-24T16:36:49Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;==Определение==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Циркуляцией''' называется поток в [[Определение сети, потока|сети]] $G(V, E)$ нулевой величины (см. рисунок 1).&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Циркул2.png|frame|справа|Рисунок 1. Пример графа и циркуляции в нем (поток/пропуск.способность)]]&lt;br /&gt;
&lt;br /&gt;
То есть [[Определение сети, потока#Определение потока|закон сохранения потока]] &amp;lt;tex&amp;gt;\sum\limits_v f(u,v)=0&amp;lt;/tex&amp;gt; должен выполняться для '''всех''' вершин графа, а значит нет нужды в истоке и стоке.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
==Постановка задачи==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;Рассмотрим сеть $G(V, E)$, в которой про каждое ребро $e_i$ известны величины: $l_i$ {{---}} минимальная пропускная способность и $c_i$ {{---}} максимальная пропускная способность. Необходимо выяснить, существует ли в этой сети циркуляция, удовлетворяющая требованиям, наложенным на пропускные способности. &lt;br /&gt;
&lt;br /&gt;
Когда все  $l_i$ равны $0$, достаточно пустить поток нулевой величины из каждой вершины, что и будет ответом. Поэтому далее в графе будут существовать ребра с положительно нижней пропускной способностью. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
==Решение==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;Для решения этой задачи заменим исходную сеть $G$ на $G'$ следующим образом. Сначала добавим в граф вершины $s$ {{---}} исток и $t$ {{---}} сток. Для каждого ребра $e_i = v_{from} \xrightarrow{l_i, c_i} v_{to}$ добавим ребра $s \xrightarrow{0, l_i} v_{to}$ и $u_{from} \xrightarrow{0, l_i} t$, а также сделаем в ребре $e_i$ изменения: $c_i = c_i - l_i, l_i = 0$ (см. рисунок 2).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Циркуляция.png|frame|center|Рисунок 2. Слева - изначальный граф. Для каждого ребра заданы его нижняя и верхняя пропускные способности. Справа - граф после преобразований ребер.]]&lt;br /&gt;
&lt;br /&gt;
Каждое ребро изначального графа заменяется на три новых. Если по ребру $e_i = (v_{from}, v_{to})$ в исходной сети протекает поток $l_i \leqslant f_i \leqslant c_i$, то в новой сети по ребру $(s, v_{to})$ должен течь поток, равный $l_i$, то есть его пропускной способности. Поток, который вытекает из $v_{from}$ по ребру в $G$, заменяется на поток, который протекает по ребрам $(v_{from}, v_{to})$ и $(v_{from}, t)$ (поскольку сумма их пропускных способностей в полученном графе равна $c_i$). Аналогично, для вершины $v_{to}$ суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети $G'$ все $l_i = 0$, то есть мы имеем обыкновенную сеть.&lt;br /&gt;
&lt;br /&gt;
Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство &amp;lt;tex&amp;gt;\sum\limits_v f(u,v) = 0&amp;lt;/tex&amp;gt; для всех вершин графа. Это равносильно существованию потока между вершинами $s$ и $t$ в сети $G'$, который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит $i$-ое ребро как минимум на $l_i$, что и является необходимым требованием. Если этот поток существует, то будет выполнено:&lt;br /&gt;
* $\sum\limits_v f(u,v)=0,$ где $u \in V'-\{s,t\}, v \in V'$, то есть для всех исходных вершин;&lt;br /&gt;
* В $G': f_i \leqslant c_i - l_i \Rightarrow 0 \leqslant f_i \leqslant c_i - l_i \Rightarrow l_i \leqslant f_i + l_i \leqslant c_i$, что удовлетворяет всем ограничениям.&lt;br /&gt;
Значит, этот поток и есть циркуляция. &lt;br /&gt;
&lt;br /&gt;
Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети $G'$ соответствующие значения минимальной пропускной способности.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;tex&amp;gt;G=\varnothing&amp;lt;/tex&amp;gt;                                           &amp;lt;font color=green&amp;gt;// пустой граф, вершины 0 и n + 1 - исток и сток, в исходном графе n вершин и m рёбер&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt;                                       &amp;lt;font color=green&amp;gt;// ребро с полями (from, to, min_cap, cap)&amp;lt;/font&amp;gt;&lt;br /&gt;
     edge &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
     edge &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.to, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.cap &amp;lt;tex&amp;gt;-e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
     edge &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from, &amp;lt;tex&amp;gt;n+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.min_cap)&lt;br /&gt;
     &amp;lt;tex&amp;gt;G = G \cup {t,g,h}&amp;lt;/tex&amp;gt;&lt;br /&gt;
 max_flow = getmaxflow(&amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;)                         &amp;lt;font color=green&amp;gt;// наибольший поток в графе G&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;e : e\in E&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;.from &amp;lt;tex&amp;gt;=s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &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;&amp;lt; e&amp;lt;/tex&amp;gt;.cap                               &amp;lt;font color=green&amp;gt;// если для текущего ребра flow &amp;lt; cap&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''return''' false&lt;br /&gt;
 '''return''' true&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
* [http://dl.dropbox.com/u/39566886/Graph-Theory-Algorithms-M-Ashraf-Iqbal.pdf M. Ashraf Iqbal {{---}}'''Graph Theory and Algorithms''']&lt;br /&gt;
* [http://e-maxx.ru/algo/flow_with_limits e-maxx]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50035</id>
		<title>Теорема о декомпозиции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50035"/>
				<updated>2015-11-24T15:06:45Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Теорема==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
о декомпозиции&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;G = (V, E)&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow_network|транспортная сеть]], &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow|поток]] в &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;O(E)&amp;lt;/tex&amp;gt; путей из истока в сток и циклов, при этом все пути и циклы будут иметь положительный поток.&lt;br /&gt;
|proof=&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;G&amp;lt;/tex&amp;gt;. Пусть из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; выходит хотя бы одно ребро с положительным потоком. Пойдем по этому ребру, попадем в вершину &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;v_1&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;t&amp;lt;/tex&amp;gt;, иначе по закону сохранения потока для вершины &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt; из нее должно выходить хотя бы одно ребро с положительным потоком в некоторую вершину &amp;lt;tex&amp;gt;v_2&amp;lt;/tex&amp;gt;. Будем продолжать этот процесс до тех пор, пока &amp;lt;tex&amp;gt;v_i&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;t&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;s&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;G = (V, E)&amp;lt;/tex&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)'''&lt;br /&gt;
     &amp;lt;tex&amp;gt; Q = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt; P = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;v = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt; v \notin P &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt; v = t &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         edge &amp;lt;tex&amp;gt;e =&amp;lt;/tex&amp;gt; NULL&lt;br /&gt;
         '''for''' &amp;lt;tex&amp;gt;u : (vu) \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt; f(vu)&amp;gt;0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt;e = (vu)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 '''break'''&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;e =&amp;lt;/tex&amp;gt; NULL&lt;br /&gt;
             '''return''' NULL&lt;br /&gt;
         &amp;lt;tex&amp;gt; Q&amp;lt;/tex&amp;gt;.push_back(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; P = P \cup \{v\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; v = u &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;v \in P &amp;lt;/tex&amp;gt;  &amp;lt;font color=green&amp;gt;// нашли цикл, удаляем из &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; все ребра, найденные до того, как &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; была включена в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.begin.from &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop_front()&lt;br /&gt;
     &amp;lt;tex&amp;gt;f(Q) = f(Q)&amp;lt;/tex&amp;gt; - &amp;lt;tex&amp;gt;\min\limits_{uv \in Q}f(uv) &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;(f, Q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''fullDecomposition()'''&lt;br /&gt;
     &amp;lt;tex&amp;gt; d = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     '''while''' (&amp;lt;tex&amp;gt;p \neq &amp;lt;/tex&amp;gt; NULL)&lt;br /&gt;
         &amp;lt;tex&amp;gt; d = d \cup p &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt; u \in V &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;p \neq &amp;lt;/tex&amp;gt; NULL)&lt;br /&gt;
             &amp;lt;tex&amp;gt; d = d \cup \{p\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;d&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;O(VE)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Действительно, каждый путь (цикл) содержит не более &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; вершин, следовательно, поиск пути (цикла) работает за &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;. Т. к. декомпозиция потока содержит &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; путей, то всего в ходе алгоритма при рассмотрении всех вершин будет осуществлено &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; поисков путей (циклов) (в остальных случаях в силу отсутствия потока через вершину поиск пути вызываться не будет). Итого суммарное время работы составит &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
* ''Ravindra Ahuja, Thomas Magnanti, James Orlin'' — '''Network flows''' — Prentice-Hall, Inc. Upper Saddle River, New Jersey, 1993.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке ]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50034</id>
		<title>Теорема о декомпозиции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50034"/>
				<updated>2015-11-24T15:01:11Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Теорема==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
о декомпозиции&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;G = (V, E)&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow_network|транспортная сеть]], &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow|поток]] в &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;O(E)&amp;lt;/tex&amp;gt; путей из истока в сток и циклов, при этом все пути и циклы имеют положительный поток.&lt;br /&gt;
|proof=&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;G&amp;lt;/tex&amp;gt;. Пусть из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; выходит хотя бы одно ребро с положительным потоком. Пойдем по этому ребру, попадем в вершину &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;v_1&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;t&amp;lt;/tex&amp;gt;, иначе по закону сохранения потока для вершины &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt; из нее должно выходить хотя бы одно ребро с положительным потоком в некоторую вершину &amp;lt;tex&amp;gt;v_2&amp;lt;/tex&amp;gt;. Будем продолжать этот процесс до тех пор, пока &amp;lt;tex&amp;gt;v_i&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;t&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;s&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;G = (V, E)&amp;lt;/tex&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)'''&lt;br /&gt;
     &amp;lt;tex&amp;gt; Q = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt; P = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;v = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt; v \notin P &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt; v = t &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         edge &amp;lt;tex&amp;gt;e =&amp;lt;/tex&amp;gt; NULL&lt;br /&gt;
         '''for''' &amp;lt;tex&amp;gt;u : (vu) \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt; f(vu)&amp;gt;0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt;e = (vu)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 '''break'''&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;e =&amp;lt;/tex&amp;gt; NULL&lt;br /&gt;
             '''return''' NULL&lt;br /&gt;
         &amp;lt;tex&amp;gt; Q&amp;lt;/tex&amp;gt;.push_back(&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; P = P \cup \{v\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; v = u &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;v \in P &amp;lt;/tex&amp;gt;  &amp;lt;font color=green&amp;gt;// нашли цикл, удаляем из &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; все ребра, найденные до того, как &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; была включена в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.begin.from &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop_front()&lt;br /&gt;
     &amp;lt;tex&amp;gt;f(Q) = f(Q)&amp;lt;/tex&amp;gt; - &amp;lt;tex&amp;gt;\min\limits_{uv \in Q}f(uv) &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;(f, Q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''fullDecomposition()'''&lt;br /&gt;
     &amp;lt;tex&amp;gt; d = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     '''while''' (&amp;lt;tex&amp;gt;p \neq &amp;lt;/tex&amp;gt; NULL)&lt;br /&gt;
         &amp;lt;tex&amp;gt; d = d \cup p &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt; u \in V &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;p \neq &amp;lt;/tex&amp;gt; NULL)&lt;br /&gt;
             &amp;lt;tex&amp;gt; d = d \cup \{p\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;d&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;O(VE)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Действительно, каждый путь (цикл) содержит не более &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; вершин, следовательно, поиск пути (цикла) работает за &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;. Т. к. декомпозиция потока содержит &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; путей, то всего в ходе алгоритма при рассмотрении всех вершин будет осуществлено &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; поисков путей (циклов) (в остальных случаях в силу отсутствия потока через вершину поиск пути вызываться не будет). Итого суммарное время работы составит &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
''Ravindra Ahuja, Thomas Magnanti, James Orlin'' — '''Network flows''' — Prentice-Hall, Inc. Upper Saddle River, New Jersey, 1993.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке ]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50032</id>
		<title>Теорема о декомпозиции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%BE_%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8&amp;diff=50032"/>
				<updated>2015-11-22T19:18:59Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Теорема==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
о декомпозиции&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;G = (V, E)&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow_network|транспортная сеть]], &amp;lt;tex&amp;gt;f&amp;lt;/tex&amp;gt; — [[Определение сети, потока#flow|поток]] в &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;O(E)&amp;lt;/tex&amp;gt; путей из истока в сток и циклов, при этом все пути и циклы имеют положительный поток.&lt;br /&gt;
|proof=&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;G&amp;lt;/tex&amp;gt;. Пусть из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; выходит хотя бы одно ребро с положительным потоком. Пойдем по этому ребру, попадем в вершину &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;v_1&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;t&amp;lt;/tex&amp;gt;, иначе по закону сохранения потока для вершины &amp;lt;tex&amp;gt;v_1&amp;lt;/tex&amp;gt; из нее должно выходить хотя бы одно ребро с положительным потоком в некоторую вершину &amp;lt;tex&amp;gt;v_2&amp;lt;/tex&amp;gt;. Будем продолжать этот процесс до тех пор, пока &amp;lt;tex&amp;gt;v_i&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;t&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;s&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;G = (V, E)&amp;lt;/tex&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)'''&lt;br /&gt;
     &amp;lt;tex&amp;gt; Q = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt; P = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;v = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt; v \notin P &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt; v = t &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''break'''&lt;br /&gt;
         edge &amp;lt;tex&amp;gt;e =&amp;lt;/tex&amp;gt; NULL&lt;br /&gt;
         '''for''' &amp;lt;tex&amp;gt;u : (vu) \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt; f(vu)&amp;gt;0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt;e = (vu)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 '''break'''&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;e =&amp;lt;/tex&amp;gt; NULL&lt;br /&gt;
             '''return''' NULL&lt;br /&gt;
         &amp;lt;tex&amp;gt; Q  = Q \cup \{e\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; P = P \cup \{v\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt; v = u &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;v \in P &amp;lt;/tex&amp;gt;&lt;br /&gt;
         удаляем из &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; все ребра, найденные до того, как &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; была включена в &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;f(Q) = f(Q)&amp;lt;/tex&amp;gt; - &amp;lt;tex&amp;gt;\min\limits_{uv \in Q}f(uv) &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;(f, Q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 '''fullDecomposition()'''&lt;br /&gt;
     &amp;lt;tex&amp;gt; d = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' (&amp;lt;tex&amp;gt;p \neq &amp;lt;/tex&amp;gt; NULL)&lt;br /&gt;
         &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt; d = d \cup p &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt; u \in V &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''while''' (&amp;lt;tex&amp;gt;p \neq &amp;lt;/tex&amp;gt; NULL)&lt;br /&gt;
             &amp;lt;tex&amp;gt;p = &amp;lt;/tex&amp;gt; simpleDecomposition(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt; d = d \cup \{p\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;d&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;O(VE)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Действительно, каждый путь (цикл) содержит не более &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; вершин, следовательно, поиск пути (цикла) работает за &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;. Т. к. декомпозиция потока содержит &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; путей, то всего в ходе алгоритма при рассмотрении всех вершин будет осуществлено &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; поисков путей (циклов) (в остальных случаях в силу отсутствия потока через вершину поиск пути вызываться не будет). Итого суммарное время работы составит &amp;lt;tex&amp;gt;O(VE)&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
''Ravindra Ahuja, Thomas Magnanti, James Orlin'' — '''Network flows''' — Prentice-Hall, Inc. Upper Saddle River, New Jersey, 1993.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке ]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B3%D1%80%D0%B0%D1%84%D0%B0&amp;diff=50014</id>
		<title>Двойственный граф планарного графа</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B3%D1%80%D0%B0%D1%84%D0%B0&amp;diff=50014"/>
				<updated>2015-11-21T18:51:12Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|definition=Граф&amp;lt;ref&amp;gt;На самом деле, ''двойственный граф'' — '''псевдограф''', поскольку в нём могут быть петли и кратные рёбра.&amp;lt;/ref&amp;gt; &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; называется '''двойственным''' (англ. ''dual graph'') к [[Укладка графа на плоскости|планарному графу]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, если:&lt;br /&gt;
# Вершины &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; соответствуют граням &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Между двумя вершинами в &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; есть ребро тогда и только тогда, когда соответствующие грани в &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; имеют общее ребро&lt;br /&gt;
}}&lt;br /&gt;
[[Файл:Dual_graph_2.png|180px|thumb|right|Граф (белые вершины) и двойственный ему (серые вершины).]]&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Чтобы для данного плоского графа &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; построить двойственный &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;, необходимо поместить по вершине &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; в каждую грань &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; (включая внешнюю), а затем, если две грани в &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; имеют общее ребро, соединить ребром соответствующие им вершины в &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; (если грани имеют несколько общих рёбер, соответствующие вершины следует соединить несколькими параллельными рёбрами). В результате всегда получится плоский псевдограф.&lt;br /&gt;
&lt;br /&gt;
Например: тетраэдр — самодвойственный граф, куб и октаэдр — двойственные, так же как додекаэдр и икосаэдр. Эти пять графов, образованные вершинами и рёбрами правильных многогранников, называют ''платоновыми''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
[[Файл:Treenflower new.png|250px|thumb|right|Дерево и двойственный к нему «цветок».‎]]&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; — ''двойственный'' к двусвязному графу &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; — ''двойственный'' к &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&lt;br /&gt;
* У одного и того же графа может быть несколько ''двойственных'', в зависимости от конкретной укладки (см. картинку)&lt;br /&gt;
* Поскольку любой трёхсвязный планарный граф допускает только одну укладку на сфере&amp;lt;ref&amp;gt;Харари, Ф. Теория графов. — М.: Книжный дом «ЛИБРОКОМ», 2009. — Теорема 11.5 — С. 130. — ISBN 978­-5­-397­-00622­-4&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;
|definition=Планарный граф называется '''самодвойственным''', если он изоморфен своему двойственному графу.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[Файл:Wheel8_new2.png|500px|thumb|left|Колесо и двойственный ему граф {{---}} тоже колесо.]]&lt;br /&gt;
 |[[Файл:K4_new.png|250px|thumb|right|&amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; (он же колесо).]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; — самодвойственные графы. Среди полных графов других самодвойственных нет.&lt;br /&gt;
|proof=Проверить, что &amp;lt;tex&amp;gt;K_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_4&amp;lt;/tex&amp;gt; полны и самодвойственны несложно. Докажем, что других нет.&amp;lt;br/&amp;gt;Поскольку грани графа переходят в вершины, количество вершин и граней в исходном графе должно совпадать, т.е. &amp;lt;tex&amp;gt;V = F&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Подставив в [[Формула Эйлера|формулу Эйлера]] имеем: &amp;lt;tex&amp;gt;2V = E + 2 \Leftrightarrow V = \dfrac{E}{2} + 1&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;В полном графе &amp;lt;tex&amp;gt;E = \dfrac{V \cdot (V - 1)}{2}&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Получаем квадратное уравнение: &amp;lt;tex&amp;gt;V^2 - 5V + 4 = 0&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Его решения: &amp;lt;tex&amp;gt;V_1 = 1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;V_2 = 4&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;Таким образом, чтобы ''полный'' граф был ''самодвойственным'', в нём должна быть ровно '''одна''' или '''четыре''' вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style='clear: both;'&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|neat=neat&lt;br /&gt;
|statement=Все колёса самодвойственны.&lt;br /&gt;
|proof=Это утверждение очевидно.&amp;lt;br/&amp;gt;Достаточно убедиться, что два варианта укладки колеса (вершина с большой степенью внутри или вершина с большой степенью снаружи) двойственны друг другу.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&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;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации==&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84 Википедия — Двойственный граф]&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/%D0%9F%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B9_%D0%B3%D1%80%D0%B0%D1%84 Википедия — Планарный граф]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49882</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49882"/>
				<updated>2015-11-13T18:24:19Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: /* Сложность */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt;. Если при этом &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;; иначе ничего не делаем.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&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;M_0&amp;lt;/tex&amp;gt; {{---}} [[Хеш-таблица|хеш-таблица]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} основная и срочная [[Очередь|очереди]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; {{---}} [[Хеш-таблица|хеш-таблица]].&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;M_1{''}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M_1{'}&amp;lt;/tex&amp;gt; [[Персистентный дек|дек]] и добавляя вершины из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в начало дека, алгоритм в худшем случае будет работать за экспоненциальное время, так делать не рекомендуется.&lt;br /&gt;
&lt;br /&gt;
В плохих случаях алгоритм Левита работает за &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;. Рассмотрим полный граф &amp;lt;tex&amp;gt;K_n&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; рёбрами, идущими в [[Лексикографический порядок|лексикографическом порядке]]:&lt;br /&gt;
* для всех вершин &amp;lt;tex&amp;gt;1 &amp;lt; i &amp;lt; j \leqslant n&amp;lt;/tex&amp;gt; вес ребра &amp;lt;tex&amp;gt;(i,j) = j - i - 1&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;w_{i,i+1}=0&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* ребро &amp;lt;tex&amp;gt;(1,n)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* для всех вершин &amp;lt;tex&amp;gt;1 &amp;lt; i &amp;lt; n&amp;lt;/tex&amp;gt; вес ребра &amp;lt;tex&amp;gt;(1,i) = w_{1,i+1} + i - 1&amp;lt;/tex&amp;gt;; от &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; вершины расстояние равно &amp;lt;tex&amp;gt;\sum\limits_{k=i-1}^{n-2}k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ясно, что кратчайший путь до каждой вершины равен &amp;lt;tex&amp;gt;0&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;2&amp;lt;/tex&amp;gt; до &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;M_0&amp;lt;/tex&amp;gt; больше не достанут. На следующем шаге добавлений не произойдёт, так как вершины больше &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; уже в очереди. На &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; шаге алгоритм улучшит расстояние до вершины &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; (что видно из веса рёбер &amp;lt;tex&amp;gt;(1,2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;(1,3)&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;\sum\limits_{k=1}^{n-2}k&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\sum\limits_{k=2}^{n-2}k&amp;lt;/tex&amp;gt; соответственно), так что её добавят в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; и обработают на &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; шаге (релаксаций не происходит). На следующем шаге из обычной очереди достанут вершину &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;, расстояние до неё, равное &amp;lt;tex&amp;gt;\sum\limits_{k=3}^{n-2}k&amp;lt;/tex&amp;gt;, на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; меньше, чем расстояние до &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; вершин. Их добавят в срочную очередь, но так как &amp;lt;tex&amp;gt;w_{24}-1=w_{34}&amp;lt;/tex&amp;gt;, то после подсчёта вершины &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; вершину &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; снова добавят в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;. Затем дойдёт очередь до вершины &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;, что вызовет релаксацию предыдущих вершин &amp;lt;tex&amp;gt;2,3,4&amp;lt;/tex&amp;gt;, затем прорелаксируют вершины &amp;lt;tex&amp;gt;2,3&amp;lt;/tex&amp;gt;, и после вершина &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. Аналогично будут происходить релаксации всех вершин при обработке вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; из очереди &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Таким образом, вершину &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; будут добавлять в срочную очередь &amp;lt;tex&amp;gt;n-i&amp;lt;/tex&amp;gt; раз (добавление вершин из очереди &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; с номером больше &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; количество добавлений &amp;quot;старшей&amp;quot; вершины &amp;lt;tex&amp;gt;i+1&amp;lt;/tex&amp;gt;. Количество добавлений вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; составит &amp;lt;tex&amp;gt;1 + \sum\limits_{k=1}^{n-i}k&amp;lt;/tex&amp;gt;, а сумма всех добавлений примерно составит &amp;lt;tex&amp;gt;O(nm)&amp;lt;/tex&amp;gt;. При обработке каждой вершины приходится обходить &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; ребер, что даёт оценку &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49881</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49881"/>
				<updated>2015-11-13T18:15:49Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt;. Если при этом &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;; иначе ничего не делаем.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&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;M_0&amp;lt;/tex&amp;gt; {{---}} [[Хеш-таблица|хеш-таблица]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} основная и срочная [[Очередь|очереди]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; {{---}} [[Хеш-таблица|хеш-таблица]].&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;M_1{''}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;M_1{'}&amp;lt;/tex&amp;gt; [[Персистентный дек|дек]] и добавляя вершины из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в начало дека, алгоритм в худшем случае будет работать за экспоненциальное время, так делать не рекомендуется.&lt;br /&gt;
&lt;br /&gt;
В плохих случаях алгоритм Левита работает за &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;. Рассмотрим полный граф &amp;lt;tex&amp;gt;K_n&amp;lt;/tex&amp;gt; с такими рёбрами, идущими в [[Лексикографический порядок|лексикографическом порядке]]:&lt;br /&gt;
* для все вершин &amp;lt;tex&amp;gt;1 &amp;lt; i &amp;lt; j \leqslant n&amp;lt;/tex&amp;gt; вес ребра &amp;lt;tex&amp;gt;(i,j) = j - i - 1&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;w_{i,i+1}=0&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* ребро &amp;lt;tex&amp;gt;(1,n)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* для всех вершин &amp;lt;tex&amp;gt;1 &amp;lt; i &amp;lt; n&amp;lt;/tex&amp;gt; вес ребра &amp;lt;tex&amp;gt;(1,i) = w_{1,i+1} + i - 1&amp;lt;/tex&amp;gt;; от &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; вершины расстояние равно &amp;lt;tex&amp;gt;\sum\limits_{k=i-1}^{n-2}k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ясно, что кратчайший путь до каждой вершины равен &amp;lt;tex&amp;gt;0&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;2&amp;lt;/tex&amp;gt; до &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;M_0&amp;lt;/tex&amp;gt; больше не достанут. На следующем шаге добавлений не произойдёт, так как вершины больше &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; уже в очереди. На &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; шаге алгоритм улучшит расстояние до вершины &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; (что видно из веса рёбер &amp;lt;tex&amp;gt;(1,2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;(1,3)&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;\sum\limits_{k=1}^{n-2}k&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\sum\limits_{k=2}^{n-2}k&amp;lt;/tex&amp;gt; соответственно), так что её добавят в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; и обработают на &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; шаге (релаксаций не происходит). На следующем шаге из обычной очереди достанут вершину &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;, расстояние до неё, равное &amp;lt;tex&amp;gt;\sum\limits_{k=3}^{n-2}k&amp;lt;/tex&amp;gt;, на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; меньше, чем расстояние до &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; вершин. Их добавят в срочную очередь, но так как &amp;lt;tex&amp;gt;w_{24}-1=w_{34}&amp;lt;/tex&amp;gt;, то после подсчёта вершины &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; вершину &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; снова добавят в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;. Затем дойдёт очередь до вершины &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;, что вызовет релаксацию предыдущих вершин &amp;lt;tex&amp;gt;2,3,4&amp;lt;/tex&amp;gt;, затем прорелаксируют вершины &amp;lt;tex&amp;gt;2,3&amp;lt;/tex&amp;gt;, и после вершина &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. Аналогично будут происходить релаксации всех вершин при обработке вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; из очереди &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Таким образом, вершину &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; будут добавлять в срочную очередь &amp;lt;tex&amp;gt;n-i&amp;lt;/tex&amp;gt; раз (добавление вершин из очереди &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; с номером больше &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; количество добавлений &amp;quot;старшей&amp;quot; вершины &amp;lt;tex&amp;gt;i+1&amp;lt;/tex&amp;gt;. Количество добавлений вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; составит &amp;lt;tex&amp;gt;1 + \sum\limits_{k=1}^{n-i}k&amp;lt;/tex&amp;gt;, а сумма всех добавлений примерно составит &amp;lt;tex&amp;gt;O(nm)&amp;lt;/tex&amp;gt;. При обработке каждой вершины приходится обходить &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; ребер, что даёт оценку &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49880</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49880"/>
				<updated>2015-11-12T19:41:19Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt;. Если при этом &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;; иначе ничего не делаем.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&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;M_0&amp;lt;/tex&amp;gt; {{---}} [[Хеш-таблица|хеш-таблица]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} основная и срочная [[Очередь|очереди]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; {{---}} [[Хеш-таблица|хеш-таблица]].&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;3n&amp;lt;/tex&amp;gt; вершинами и такими рёбрами:&lt;br /&gt;
* ребро &amp;lt;tex&amp;gt;(1,&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2n + 1)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;2^{n/2}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* для нечётных вершин &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;2n+1 \leqslant i \leqslant 3n&amp;lt;/tex&amp;gt; идёт ребро &amp;lt;tex&amp;gt;(i,i+2)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;2^{(3n-i)/2}&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 \leqslant i &amp;lt; 3n&amp;lt;/tex&amp;gt; идёт ребро &amp;lt;tex&amp;gt;(i,i+1)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ясно, что кратчайший путь до каждой вершины равен &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, но в плохом случае алгоритм будет часто пересчитывать последние вершины. На 1 шаге в очередь положат две вершины: с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; (после нескольких шагов вершинам от &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;2n + 1&amp;lt;/tex&amp;gt; алгоритм сделает веса равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;) и с номером &amp;lt;tex&amp;gt;2n + 1&amp;lt;/tex&amp;gt; (через такое же число шагов вершинам от &amp;lt;tex&amp;gt;2n + 2&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;3n&amp;lt;/tex&amp;gt; будет задан вес &amp;lt;tex&amp;gt;2^{n/2}&amp;lt;/tex&amp;gt;). Оставшиеся &amp;lt;tex&amp;gt;n-2&amp;lt;/tex&amp;gt; вершины, находящиеся в очереди &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;, образуют последовательность маленьких циклов длины &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;, в которых два ребра нулевого веса. Каждый такой цикл увеличит количество добавлений следующих двух вершин в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Алгоритм будет часто пересчитывать расстояние до последних вершин, так как их часто добавляли в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49879</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49879"/>
				<updated>2015-11-12T19:28:47Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt;. Если при этом &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;; иначе ничего не делаем.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&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;M_0&amp;lt;/tex&amp;gt; {{---}} хэш-сет,&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} основная и срочная [[Очередь|очереди]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; {{---}} хэш-сет.&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;3n&amp;lt;/tex&amp;gt; вершинами и такими рёбрами:&lt;br /&gt;
* ребро &amp;lt;tex&amp;gt;(1,&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2n + 1)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;2^{n/2}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* для нечётных вершин &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;2n+1 \leqslant i \leqslant 3n&amp;lt;/tex&amp;gt; идёт ребро &amp;lt;tex&amp;gt;(i,i+2)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;2^{(3n-i)/2}&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 \leqslant i &amp;lt; 3n&amp;lt;/tex&amp;gt; идёт ребро &amp;lt;tex&amp;gt;(i,i+1)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ясно, что кратчайший путь до каждой вершины равен &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, но в плохом случае алгоритм будет часто пересчитывать последние вершины. На 1 шаге в очередь положат две вершины: с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; (после нескольких шагов вершинам от &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;2n + 1&amp;lt;/tex&amp;gt; алгоритм сделает веса равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;) и с номером &amp;lt;tex&amp;gt;2n + 1&amp;lt;/tex&amp;gt; (через такое же число шагов вершинам от &amp;lt;tex&amp;gt;2n + 2&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;3n&amp;lt;/tex&amp;gt; будет задан вес &amp;lt;tex&amp;gt;2^{n/2}&amp;lt;/tex&amp;gt;). Оставшиеся &amp;lt;tex&amp;gt;n-2&amp;lt;/tex&amp;gt; вершины, находящиеся в очереди &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;, образуют последовательность маленьких циклов длины &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;, в которых два ребра нулевого веса. Каждый такой цикл увеличит количество добавлений следующих двух вершин в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Алгоритм будет часто пересчитывать расстояние до последних вершин, так как их часто добавляли в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49796</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49796"/>
				<updated>2015-11-08T14:10:31Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых еще не вычислено.&lt;br /&gt;
&lt;br /&gt;
Для хранения вершин используем следующие структуры данных:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} хэш-сет,&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} основная и срочная [[Очередь|очереди]],&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt;. Если при этом &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;; иначе ничего не делаем.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;3n&amp;lt;/tex&amp;gt; вершинами и такими рёбрами:&lt;br /&gt;
* ребро &amp;lt;tex&amp;gt;(1,&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2n + 1)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;2^{n/2}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* для нечётных вершин &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; : &amp;lt;tex&amp;gt;2 \cdot n+1 \leqslant i \leqslant 3n&amp;lt;/tex&amp;gt; идёт ребро &amp;lt;tex&amp;gt;(i,i+2)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;2^{(3n-i)/2}&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 \leqslant i &amp;lt; 3n&amp;lt;/tex&amp;gt; идёт ребро &amp;lt;tex&amp;gt;(i,i+1)&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ясно, что кратчайший путь до каждой вершины равен &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, но в плохом случае алгоритм будет часто пересчитывать последние вершины. На 1 шаге в очередь положат две вершины: с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; (после нескольких шагов вершинам от &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;2n + 1&amp;lt;/tex&amp;gt; алгоритм сделает веса равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;) и с номером &amp;lt;tex&amp;gt;2n + 1&amp;lt;/tex&amp;gt; (через такое же число шагов вершинам от &amp;lt;tex&amp;gt;2n + 2&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;3n&amp;lt;/tex&amp;gt; будет задан вес &amp;lt;tex&amp;gt;2^{n/2}&amp;lt;/tex&amp;gt;). Оставшиеся &amp;lt;tex&amp;gt;n-2&amp;lt;/tex&amp;gt; вершины находятся в очереди &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;, алгоритм начнёт часто пересчитывать их вес, что приведёт к их многократному добавлению в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49789</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49789"/>
				<updated>2015-11-08T11:04:15Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt;. Если при этом &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;; иначе ничего не делаем.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;3\cdot n&amp;lt;/tex&amp;gt; вершинами и такими рёбрами: от вершины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; ребро веса &amp;lt;tex&amp;gt;2^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+2&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;...&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;3 \cdot n&amp;lt;/tex&amp;gt;; вес &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого звена &amp;lt;tex&amp;gt;2^{n-i}&amp;lt;/tex&amp;gt;), а также цепь рёбер от &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;3 \cdot n&amp;lt;/tex&amp;gt; (вес каждого звена &amp;lt;tex&amp;gt;0&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;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49781</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49781"/>
				<updated>2015-11-07T18:21:02Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;u=(M_1^{''} = \varnothing&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;?&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.pop() &amp;lt;tex&amp;gt;:&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt;.pop()&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;K_n&amp;lt;/tex&amp;gt; с достаточно большим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; и весами &amp;lt;tex&amp;gt;w_{uv} =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 v - u - 1, &amp;amp; u &amp;gt; 1\\&lt;br /&gt;
 w_{un}\cdot2, &amp;amp; u = 1, v = n - 1 \\&lt;br /&gt;
 n-2, &amp;amp; u = 1, v = n\\&lt;br /&gt;
 w_{uv+1} + v - u, &amp;amp; u = 1, v &amp;lt; n-1&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;, рёбра идут в [[Лексикографический порядок|лексикографическом порядке]]. Добавление вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; в очередь и последующая её обработка влекут добавление из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; всех её предыдущих вершин, начиная со &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-ой; дойдя до вершины &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt;, в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; снова добавятся вершины меньше &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt; (кроме первой). Таким образом, вершину &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; добавят в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;130&amp;quot;&amp;gt;\sum\limits_{k=1}^{n-i}k = \dfrac 12\cdot(n-i)\cdot(n-i+1)&amp;lt;/tex&amp;gt; раз, всего в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; будет  &amp;lt;tex&amp;gt;\dfrac 16\cdot n\cdot(n^2-3n+2)&amp;lt;/tex&amp;gt; добавлений. В очень плохих случаях вершина &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; может помещаться в очередь &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;2^{n-i}&amp;lt;/tex&amp;gt; раз, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm MAXimal :: algo :: Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49778</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49778"/>
				<updated>2015-11-07T15:52:18Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно),&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь,&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь;&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;),&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''int''' &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
       &amp;lt;tex&amp;gt;u = M_1^{''}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''else'''&lt;br /&gt;
       &amp;lt;tex&amp;gt;u = M_1{'}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' v &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;K_n&amp;lt;/tex&amp;gt; с достаточно большим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; и весами &amp;lt;tex&amp;gt;w_{uv} =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 v - u - 1, &amp;amp; u &amp;gt; 1\\&lt;br /&gt;
 w_{un}\cdot2, &amp;amp; u = 1, v = n - 1 \\&lt;br /&gt;
 n-2, &amp;amp; u = 1, v = n\\&lt;br /&gt;
 w_{uv+1} + v - u, &amp;amp; u = 1, v &amp;lt; n-1&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;, рёбра идут в [[Лексикографический порядок|лексикографическом порядке]]. Добавление вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; в очередь и последующая её обработка влекут добавление из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; всех её предыдущих вершин, начиная со &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-ой; дойдя до вершины &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt;, в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; снова добавятся вершины меньше &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt; (кроме первой). Таким образом, вершину &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; добавят в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;130&amp;quot;&amp;gt;\sum\limits_{k=1}^{n-i}k = \dfrac 12\cdot(n-i)\cdot(n-i+1)&amp;lt;/tex&amp;gt; раз, всего в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; будет  &amp;lt;tex&amp;gt;\dfrac 16\cdot n\cdot(n^2-3n+2)&amp;lt;/tex&amp;gt; добавлений. В очень плохих случаях вершина &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; может помещаться в очередь &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;2^{n-i}&amp;lt;/tex&amp;gt; раз, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим уступает алгоритму [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm e-maxx — Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49765</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49765"/>
				<updated>2015-11-06T19:44:16Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно)&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две [[Очередь|очереди]]:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt; возможны три случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;)&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;d[u] = \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt;u : u \neq s&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;u \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''int''' &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
       &amp;lt;tex&amp;gt;u = M_1^{''}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''else'''&lt;br /&gt;
       &amp;lt;tex&amp;gt;u = M_1{'}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v : uv \in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' v &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] =&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;d[v], d[u] + w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''else if''' &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;d[v] &amp;gt; d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;d[v] = d[u] + w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;u&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;K_n&amp;lt;/tex&amp;gt; с достаточно большим n и весами &amp;lt;tex&amp;gt;w_{uv} =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 v - u - 1, &amp;amp; u &amp;gt; 1; u = 1 и v = n\\&lt;br /&gt;
 w_{un}*2, &amp;amp; u = 1, v = n - 1 \\&lt;br /&gt;
 w_{uv+1} + v - u, &amp;amp; u = 1, v &amp;lt; n-1&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;, рёбра идут в [[Лексикографический порядок|лексикографическом порядке]]. Добавление &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой вершины в очередь и последующая её обработка влекут добавление из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; всех её предыдущих вершин, начиная со &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-ой; дойдя до вершины &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt;, в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; снова добавятся вершины меньше &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt;-ой (кроме первой). Таким образом, количество добавлений &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой вершины в &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; составит &amp;lt;tex dpi=&amp;quot;130&amp;quot;&amp;gt;\sum\limits_{k=1}^{n-i} k&amp;lt;/tex&amp;gt; раз. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм A*]]&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://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Википедия — Алгоритм Левита]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm e-maxx — Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49735</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49735"/>
				<updated>2015-11-06T08:59:51Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно)&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две очереди:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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;M_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Далее, для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt;:&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;)&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' u : u &amp;lt;tex&amp;gt;\in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    d[v] &amp;lt;tex&amp;gt;\leftarrow \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 d[s] &amp;lt;tex&amp;gt;\leftarrow 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(s)&lt;br /&gt;
 '''for''' u : u &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; s  '''and''' uv &amp;lt;tex&amp;gt;\in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.push(u)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''int''' u &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''else :'''&lt;br /&gt;
       '''int''' u &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{'}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''for''' v : uv &amp;lt;tex&amp;gt;\in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(v)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(v)&lt;br /&gt;
          d[v] &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; min(d[v], d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          d[v] = min(d[v], d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_0&amp;lt;/tex&amp;gt; '''and''' d[v] &amp;lt;tex&amp;gt;&amp;gt;&amp;lt;/tex&amp;gt; d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(v)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(v)&lt;br /&gt;
          d[v] &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.push(u)&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= В конце работы алгоритма не найдется такое ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;K_n&amp;lt;/tex&amp;gt; с достаточно большим n и весами &amp;lt;tex&amp;gt;w_{uv} =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; u &amp;gt; 1 \\&lt;br /&gt;
 n - v + 1, &amp;amp; u = 1 \\&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt; при обработке &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой вершины из множества &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt; будет происходить релаксация &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt; рёбер и их добавление в срочную &amp;lt;tex&amp;gt;M_1{''}&amp;lt;/tex&amp;gt; очередь.Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Алгоритм Левита - Википедия]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49734</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49734"/>
				<updated>2015-11-05T19:54:06Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно)&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две очереди:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Далее, для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt;:&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;)&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' u : u &amp;lt;tex&amp;gt;\in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    d[v] &amp;lt;tex&amp;gt;\leftarrow \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 d[s] &amp;lt;tex&amp;gt;\leftarrow 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(s)&lt;br /&gt;
 '''for''' u : u &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; s  '''and''' uv &amp;lt;tex&amp;gt;\in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.push(u)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''int''' u &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''else :'''&lt;br /&gt;
       '''int''' u &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{'}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''for''' v : uv &amp;lt;tex&amp;gt;\in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(v)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(v)&lt;br /&gt;
          d[v] &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; min(d[v], d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          d[v] = min(d[v], d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_0&amp;lt;/tex&amp;gt; '''and''' d[v] &amp;lt;tex&amp;gt;&amp;gt;&amp;lt;/tex&amp;gt; d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(v)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(v)&lt;br /&gt;
          d[v] &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.push(u)&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&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;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;K_n&amp;lt;/tex&amp;gt; с достаточно большим n и такими весами, что: &amp;lt;tex&amp;gt;w_{uv} = 0&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;u \neq 1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;w_{uv} = n - v + 2&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt;.Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Алгоритм Левита - Википедия]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49733</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%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0&amp;diff=49733"/>
				<updated>2015-11-05T19:51:05Z</updated>
		
		<summary type="html">&lt;p&gt;Lehanyich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины &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;d_i&amp;lt;/tex&amp;gt; {{---}} текущая длина кратчайшего пути до вершины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Изначально, все элементы &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, кроме &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-го равны бесконечности; &amp;lt;tex&amp;gt;d[s] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Разделим вершины на три множества:&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых уже вычислено (возможно, не окончательно)&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; {{---}} вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две очереди:&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt; {{---}} основная очередь&lt;br /&gt;
# &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; {{---}} срочная очередь&lt;br /&gt;
* &amp;lt;tex&amp;gt;M_2&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;M_2&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; помещается в множество &amp;lt;tex&amp;gt;M_1&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_1&amp;lt;/tex&amp;gt;. Если очередь &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt; не пуста, то вершина берется из нее, иначе из &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. Далее, для каждого ребра &amp;lt;tex&amp;gt;uv \in E&amp;lt;/tex&amp;gt;:&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_2&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; переводится в конец очереди &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;. При этом &amp;lt;tex&amp;gt;d_v \gets d_u + w_{uv}&amp;lt;/tex&amp;gt; (производится релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;)&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_1&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt;&lt;br /&gt;
* если &amp;lt;tex&amp;gt;v \in M_0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_v &amp;gt; d_u + w_{uv}&amp;lt;/tex&amp;gt;, то происходит релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; помещается в &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;&lt;br /&gt;
В конце шага помещаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм заканчивает работу, когда множество &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; становится пустым.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
&lt;br /&gt;
 '''for''' u : u &amp;lt;tex&amp;gt;\in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    d[v] &amp;lt;tex&amp;gt;\leftarrow \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
 d[s] &amp;lt;tex&amp;gt;\leftarrow 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(s)&lt;br /&gt;
 '''for''' u : u &amp;lt;tex&amp;gt;\neq&amp;lt;/tex&amp;gt; s  '''and''' uv &amp;lt;tex&amp;gt;\in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.push(u)&lt;br /&gt;
 '''while''' &amp;lt;tex&amp;gt;M_1^{'} \neq \varnothing&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''if''' &amp;lt;tex&amp;gt;M_1^{''} \neq \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''int''' u &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''else :'''&lt;br /&gt;
       '''int''' u &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;M_1{'}&amp;lt;/tex&amp;gt;.pop()&lt;br /&gt;
    '''for''' v : uv &amp;lt;tex&amp;gt;\in E&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{'}&amp;lt;/tex&amp;gt;.push(v)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;.remove(v)&lt;br /&gt;
          d[v] &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; min(d[v], d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
          d[v] = min(d[v], d[u] + &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' v &amp;lt;tex&amp;gt;\in M_0&amp;lt;/tex&amp;gt; '''and''' d[v] &amp;lt;tex&amp;gt;&amp;gt;&amp;lt;/tex&amp;gt; d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_1^{''}&amp;lt;/tex&amp;gt;.push(v)&lt;br /&gt;
          &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.remove(v)&lt;br /&gt;
          d[v] &amp;lt;tex&amp;gt;=&amp;lt;/tex&amp;gt; d[u] &amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;w_{uv}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;.push(u)&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;M_0&amp;lt;/tex&amp;gt; окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt; тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;. Тогда за конечное число шагов все вершины окажутся в &amp;lt;tex&amp;gt;M_0&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;uv&amp;lt;/tex&amp;gt;, что его релаксация будет успешной&lt;br /&gt;
|proof= Предположим обратное. Тогда рассмотрим 2 случая:&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt; позже &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Тогда должна была произойти релаксация ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; и она была неуспешной. Значит, такого варианта не может быть&lt;br /&gt;
# Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; попала в &amp;lt;tex&amp;gt;M_0&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;M_0&amp;lt;/tex&amp;gt; расстояние до нее не менялось (иначе, вершина была бы извлечена из &amp;lt;tex&amp;gt;M_0&amp;lt;/tex&amp;gt;). Вес ребра &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; тоже не меняется. Значит, и релаксация ребра &amp;lt;tex&amp;gt;uv&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;K_n&amp;lt;/tex&amp;gt; с достаточно большим n и такими весами, что: &amp;lt;tex&amp;gt;w_{uv} = 0&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;u \neq 1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;w_{uv} = n - v + 2&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt;.Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]].&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Алгоритм Левита - Википедия]&lt;br /&gt;
* [http://e-maxx.ru/algo/levit_algorithm Алгоритм Левита]&lt;br /&gt;
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>Lehanyich</name></author>	</entry>

	</feed>