Схема алгоритма Диница — различия между версиями
Gaudima (обсуждение | вклад) |
м (rollbackEdits.php mass rollback) |
||
(не показано 8 промежуточных версий 5 участников) | |||
Строка 1: | Строка 1: | ||
== Определение слоистой сети == | == Определение слоистой сети == | ||
− | Для начала определим для каждой вершины <tex>v</tex> данной сети <tex>G</tex> длину кратчайшего <tex>s \leadsto v</tex> пути из истока и обозначим | + | Для начала определим для каждой вершины <tex>v</tex> данной сети <tex>G</tex> длину кратчайшего <tex>s \leadsto v</tex> пути из истока и обозначим её <tex>d[v]</tex> (для этого можно воспользоваться [[Обход в ширину|обходом в ширину]]). |
− | В слоистую сеть включаем только те | + | В слоистую сеть включаем только те рёбра <tex>(u,v)</tex> исходной сети, для которых <tex>d[u] + 1 = d[v]</tex>. |
Полученная сеть ациклична, и любой <tex>s \leadsto t</tex> путь в слоистой сети является кратчайшим путём в исходной, из свойств обхода в ширину. | Полученная сеть ациклична, и любой <tex>s \leadsto t</tex> путь в слоистой сети является кратчайшим путём в исходной, из свойств обхода в ширину. | ||
[[Файл:Слоистая_сеть.png|500px |thumb|center| Слоистая сеть с пятью слоями. <tex>s = 0, t = 6</tex>]] | [[Файл:Слоистая_сеть.png|500px |thumb|center| Слоистая сеть с пятью слоями. <tex>s = 0, t = 6</tex>]] | ||
− | В примере | + | В примере рёбра, обозначенные пунктиром, не входят в слоистую сеть. |
− | Слоистую сеть для графа G будем называть '''вспомогательной сетью'''. | + | Слоистую сеть для графа <tex>G</tex> будем называть '''вспомогательной сетью'''. |
== Алгоритм == | == Алгоритм == | ||
Строка 16: | Строка 16: | ||
#Для каждого ребра <tex>(u,v)</tex> данной сети <tex>G</tex> зададим <tex>f(u,v) = 0</tex>. | #Для каждого ребра <tex>(u,v)</tex> данной сети <tex>G</tex> зададим <tex>f(u,v) = 0</tex>. | ||
#Построим вспомогательную сеть <tex>G_L</tex> из [[Дополняющая сеть, дополняющий путь|дополняющей сети]] <tex>G_f</tex> данного графа <tex>G</tex>. Если <tex>d[t] = \infty</tex>, остановиться и вывести <tex>f</tex>. | #Построим вспомогательную сеть <tex>G_L</tex> из [[Дополняющая сеть, дополняющий путь|дополняющей сети]] <tex>G_f</tex> данного графа <tex>G</tex>. Если <tex>d[t] = \infty</tex>, остановиться и вывести <tex>f</tex>. | ||
− | #[[Алгоритм поиска блокирующего потока в ациклической сети| | + | #[[Алгоритм поиска блокирующего потока в ациклической сети|Найдём блокирующий поток]] <tex>f'</tex> в <tex>G_L</tex>. |
− | #Дополним поток <tex>f</tex> найденным потоком <tex>f'</tex> и | + | #Дополним поток <tex>f</tex> найденным потоком <tex>f'</tex> и перейдём к шагу 2. |
=== Корректность алгоритма === | === Корректность алгоритма === | ||
Строка 29: | Строка 29: | ||
Расстояние между истоком и стоком строго увеличивается после каждой фазы алгоритма, т.е. <tex>d'[t] > d[t]</tex>, где <tex>d'[t]</tex> — значение, полученное на следующей фазе алгоритма. | Расстояние между истоком и стоком строго увеличивается после каждой фазы алгоритма, т.е. <tex>d'[t] > d[t]</tex>, где <tex>d'[t]</tex> — значение, полученное на следующей фазе алгоритма. | ||
|proof= | |proof= | ||
− | Проведём доказательство от противного. Пусть длина кратчайшего пути из истока в сток останется неизменной после очередной фазы алгоритма. Вспомогательная сеть строится по остаточной. Из предположения следует, что в остаточной сети | + | Проведём доказательство от противного. Пусть длина кратчайшего пути из истока в сток останется неизменной после очередной фазы алгоритма. Вспомогательная сеть строится по остаточной. Из предположения следует, что в остаточной сети будут содержаться только рёбра остаточной сети перед выполнением данной фазы, либо обратные к ним. Из этого получаем, что нашёлся <tex>s \leadsto t</tex> путь, который не содержит насыщенных рёбер и имеет ту же длину, что и кратчайший путь. Но этот путь должен был быть «заблокирован» блокирующим потоком, чего не произошло. Получили противоречие. Значит длина изменилась. |
}} | }} | ||
Поскольку длина кратчайшего <tex>s \leadsto t</tex> пути не может превосходить <tex>n - 1</tex>, то, следовательно, алгоритм Диница совершает не более <tex>n - 1</tex> фазы. | Поскольку длина кратчайшего <tex>s \leadsto t</tex> пути не может превосходить <tex>n - 1</tex>, то, следовательно, алгоритм Диница совершает не более <tex>n - 1</tex> фазы. | ||
Строка 41: | Строка 41: | ||
<tex>f[u][v]</tex> {{---}} поток через ребро <tex>(uv)</tex>. | <tex>f[u][v]</tex> {{---}} поток через ребро <tex>(uv)</tex>. | ||
− | <tex>p[u]</tex> {{---}} [[Алгоритм_поиска_блокирующего_потока_в_ациклической_сети#.D0.A3.D0.B4.D0.B0.D0.BB.D1.8F.D1.8E.D1.89.D0.B8.D0.B9_.D0.BE.D0.B1.D1.85.D0.BE.D0.B4 | номер первого | + | <tex>p[u]</tex> {{---}} [[Алгоритм_поиска_блокирующего_потока_в_ациклической_сети#.D0.A3.D0.B4.D0.B0.D0.BB.D1.8F.D1.8E.D1.89.D0.B8.D0.B9_.D0.BE.D0.B1.D1.85.D0.BE.D0.B4 | номер первого неудалённого ребра, идущего из u]] |
'''bool''' bfs(): | '''bool''' bfs(): | ||
Строка 65: | Строка 65: | ||
delta = dfs(v, min(minC, c[u][v] - f[u][v])) | delta = dfs(v, min(minC, c[u][v] - f[u][v])) | ||
'''if''' delta != 0 | '''if''' delta != 0 | ||
− | f[u][v] += delta <font color="darkgreen">// насыщаем | + | f[u][v] += delta <font color="darkgreen">// насыщаем рёбра по пути dfs</font> |
f[v][u] -= delta | f[v][u] -= delta | ||
'''return''' delta | '''return''' delta | ||
Строка 80: | Строка 80: | ||
flow = dfs(s, <tex>\infty</tex>) | flow = dfs(s, <tex>\infty</tex>) | ||
'''return''' maxFlow | '''return''' maxFlow | ||
+ | |||
== Источники == | == Источники == | ||
− | *[http:// | + | *[http://ru.wikipedia.org/wiki/Алгоритм_Диница Википедия {{---}} Алгоритм Диница] |
− | *[http:// | + | *[http://www.e-maxx.ru/algo/dinic MAXimal::algo::Алгоритм Диница] |
*Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — С. 1296. — ISBN 5-8489-0857-4 | *Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — С. 1296. — ISBN 5-8489-0857-4 | ||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Задача о максимальном потоке ]] | [[Категория: Задача о максимальном потоке ]] |
Текущая версия на 19:15, 4 сентября 2022
Содержание
Определение слоистой сети
Для начала определим для каждой вершины обходом в ширину).
данной сети длину кратчайшего пути из истока и обозначим её (для этого можно воспользоватьсяВ слоистую сеть включаем только те рёбра
исходной сети, для которых . Полученная сеть ациклична, и любой путь в слоистой сети является кратчайшим путём в исходной, из свойств обхода в ширину.
В примере рёбра, обозначенные пунктиром, не входят в слоистую сеть.
Слоистую сеть для графа
будем называть вспомогательной сетью.Алгоритм
Пусть дана сеть. Требуется найти в этой сети поток из в максимальной величины.
Схема алгоритма
- Для каждого ребра данной сети зададим .
- Построим вспомогательную сеть дополняющей сети данного графа . Если , остановиться и вывести . из
- Найдём блокирующий поток в .
- Дополним поток найденным потоком и перейдём к шагу 2.
Корректность алгоритма
Покажем, что если алгоритм завершается, то на выходе у него получается поток именно максимальной величины.
В самом деле, предположим, что в какой-то момент во вспомогательной сети, построенной для остаточной сети, не удалось найти блокирующий поток. Это означает, что сток вообще не достижим во вспомогательной сети из истока. Но поскольку она содержит в себе все кратчайшие пути из истока в остаточной сети, это в свою очередь означает, что в остаточной сети нет пути из истока в сток. Следовательно, применяя теорему Форда-Фалкерсона, получаем, что текущий поток в самом деле максимален.
Асимптотика алгоритма
Теорема: |
Расстояние между истоком и стоком строго увеличивается после каждой фазы алгоритма, т.е. , где — значение, полученное на следующей фазе алгоритма. |
Доказательство: |
Проведём доказательство от противного. Пусть длина кратчайшего пути из истока в сток останется неизменной после очередной фазы алгоритма. Вспомогательная сеть строится по остаточной. Из предположения следует, что в остаточной сети будут содержаться только рёбра остаточной сети перед выполнением данной фазы, либо обратные к ним. Из этого получаем, что нашёлся | путь, который не содержит насыщенных рёбер и имеет ту же длину, что и кратчайший путь. Но этот путь должен был быть «заблокирован» блокирующим потоком, чего не произошло. Получили противоречие. Значит длина изменилась.
Поскольку длина кратчайшего динамические деревья Слетора и Тарьяна.
пути не может превосходить , то, следовательно, алгоритм Диница совершает не более фазы. Таким образом, в зависимости от того, каким алгоритмом нахождения блокирующего потока мы пользовались, весь алгоритм Диница может выполняться за или за . Также возможно достичь асимптотики , если использоватьРеализация
В данной реализации не строится вспомогательная сеть
, а вычисляются значения — кратчайших путей .— пропускная способность ребра .
— поток через ребро .
номер первого неудалённого ребра, идущего из u
—bool bfs(): заполняем массив d значениями, равнымиd[s] = 0 Q.push(s) while !Q.isEmpty u = Q.pop() for if f[u][v] < c[u][v] and d[v] == d[v] = d[u] + 1 Q.push(v) return d[t] !=
// поиск блокирующего потока
// u — номер вершины
// minC — минимальная пропускная способность дополняющей сети на пройденном dfs пути
int dfs(u, minC):
if u == t or minC == 0
return minC
for v = p[u] to
if d[v] == d[u] + 1 // это условие эквивалентно поиску во вспомогательной слоистой сети
delta = dfs(v, min(minC, c[u][v] - f[u][v]))
if delta != 0
f[u][v] += delta // насыщаем рёбра по пути dfs
f[v][u] -= delta
return delta
p[u]++
return 0
int findMaxFlow(): maxFlow = 0 while bfs() // пересчитываем d[i], заодно проверяем достижима ли t из s заполняем p нулями flow = dfs(s,) while flow != 0 maxFlow += flow flow = dfs(s, ) return maxFlow
Источники
- Википедия — Алгоритм Диница
- MAXimal::algo::Алгоритм Диница
- Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — С. 1296. — ISBN 5-8489-0857-4