Венгерский алгоритм решения задачи о назначениях — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(бета-версия)
Строка 12: Строка 12:
 
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.
 
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.
 
|proof=
 
|proof=
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. Отсюда все следует.
+
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. При изменении весов всех ребер, инцидентных ей, на одно и то же число, выбранное ребро останется оптимальным.
 
}}
 
}}
  
Далее будем рассматривать только графы с неотрицательной весовой функцией, так задачу о назначениях на остальных графах можно свести к этим.
+
Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.
  
 
{{Лемма
 
{{Лемма
 
|statement=
 
|statement=
Выделим в множествах <tex>X</tex> и <tex>Y</tex> подмножества <tex>X', Y'</tex>. Если прибавить ко всем весам ребер, инцидентных вершинам из <tex>X</tex>, прибавить, а потом от всех весов ребер, инцидентных вершинам из <tex>Y</tex>, отнять <tex>d = \min{c(x, y)|x \in X', y \in Y\backslash Y'}</tex>, то:
+
Выделим в множествах <tex>X</tex> и <tex>Y</tex> подмножества <tex>X', Y'</tex>. Если прибавить ко всем весам ребер, инцидентных вершинам из <tex>X</tex>, прибавить, а потом от всех весов ребер, инцидентных вершинам из <tex>Y</tex>, отнять <tex>d = \min \{c(x, y)|x \in X', y \in Y\backslash Y'\}</tex>, то:
 
# веса всех ребер графа останутся неотрицательными;
 
# веса всех ребер графа останутся неотрицательными;
 
# Веса ребер вида <tex>xy</tex>, где <tex>x \in X', y \in Y'</tex> или <tex>x \in X \backslash X', y \in Y \backslash Y'</tex>, не изменятся.
 
# Веса ребер вида <tex>xy</tex>, где <tex>x \in X', y \in Y'</tex> или <tex>x \in X \backslash X', y \in Y \backslash Y'</tex>, не изменятся.
 
|proof=
 
|proof=
ну тут кагбе все очевидно, лол
+
Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества <tex> X' </tex> и <tex> Y' </tex> состоят из первых элементов множеств <tex> X </tex> и <tex> Y </tex> соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:
 +
 
 +
<table border = '1' bordercolor = 'black' rules = 'rows' cellpadding = '5'>
 +
  <tr>
 +
    <td>  </td>
 +
    <td> <tex> X' </tex> </td>
 +
    <td> <tex> X \backslash X' </tex> </td>
 +
  </tr>
 +
  <tr>
 +
    <td> <tex> Y' </tex> </td>
 +
    <td> <tex> A + d - d </tex> </td>
 +
    <td> <tex> B - d </tex> </td>
 +
  </tr>
 +
  <tr>
 +
    <td> <tex> Y \backslash Y' </tex> </td>
 +
    <td> <tex> C + d </tex> </td>
 +
    <td> <tex> D </tex> </td>
 +
  </tr>
 +
</table>
 +
 
 +
Веса группы <tex> A </tex> будут сначала увеличены, а потом уменьшены на <tex> d </tex>, поэтому они не изменятся, веса группы <tex> D </tex> вообще изменяться не будут. Все веса группы <tex> B </tex> будут уменьшены на <tex> d </tex>, но <tex> d </tex> - минимум среди этих весов, поэтому они останутся неотрицательными.
 +
 
 
}}
 
}}
  
 
{{Лемма
 
{{Лемма
 
|statement=
 
|statement=
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным
+
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.
 
|proof=
 
|proof=
 
Действительно, паросочетание с какими-то другими весами ребер имеет больший вес и оптимальным не является.
 
Действительно, паросочетание с какими-то другими весами ребер имеет больший вес и оптимальным не является.
Строка 42: Строка 63:
 
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.
 
# Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.
 
# Ищем в текущем графе полное паросочетание из ребер нулевого веса:  
 
# Ищем в текущем графе полное паросочетание из ребер нулевого веса:  
## Если оно найдено, то желаемый результат достигнут.
+
#
 +
## Если оно найдено, то желаемый результат достигнут, алгоритм закончен.
 
## В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как нахождение минимального контролирующего множества в двудольном графе). Теперь применим преобразование из леммы 2, взяв в качестве <tex> X' </tex> и <tex> Y' </tex> вершины левой и правой долей минимального контролирующего множества. Очевидно, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.
 
## В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как нахождение минимального контролирующего множества в двудольном графе). Теперь применим преобразование из леммы 2, взяв в качестве <tex> X' </tex> и <tex> Y' </tex> вершины левой и правой долей минимального контролирующего множества. Очевидно, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.
  
 
== Анализ времени работы ==
 
== Анализ времени работы ==
  
<tex> O(n^3) </tex> и баста!
+
Поиск максимального паросочетания или минимального контролирующего множества в двудольном графе совершается за <tex> O(n^2) </tex> операций. При каждом повторении шагов 1-3 в матрице весов появляется новый нуль, который увеличивает размер максимального паросочетания хотя бы на 1, поэтому всего будет совершено <tex> O(n) </tex> итераций внешнего цикла. Поэтому суммарная асимптотика работы данного алгоритма - <tex> O(n^3) </tex>.
  
 
== Ссылки ==
 
== Ссылки ==
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&table=2&up=0 Статья, которая может помочь]
+
* [http://acm.mipt.ru/twiki/bin/view/Algorithms/HungarianAlgorithmCPP?sortcol=5&table=2&up=0 Реализация венгерского алгоритма на C++]
 
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм w:Венгерский алготитм]
 
* [http://ru.wikipedia.org/wiki/Венгерский_алгоритм w:Венгерский алготитм]
 
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]
 
* [http://rain.ifmo.ru/cat/view.php/vis/graph-flow-match/hungarian-2002 Визуализатор алгоритма]
  
 
== Литература ==
 
== Литература ==
* Асанов М., Баранский В., Расин В. - Дискретная математика: Графы, матроиды, алгоритмы — Ижевск: ННЦ "Регулярная и хаотическая динамика", 2001, 288 стр.
+
* Асанов М., Баранский В., Расин В. - Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.
  
 
[[Категория: Задача о потоке минимальной стоимости]]
 
[[Категория: Задача о потоке минимальной стоимости]]

Версия 02:24, 5 января 2012

Венгерский алгоритм, придуманный Х. Куном в 1955 году, решает задачу о назначениях за [math] O(n^3) [/math] операций.

Постановка задачи

Пусть дан взвешенный полный двудольный граф [math] K_{n, n} [/math], нужно найти в нем полное паросочетание минимального веса. Вес паросочетания определяется как сумма весов его ребер.


Некоторые полезные соображения

Лемма:
Если веса всех ребер графа, инцидентных какой-либо вершине, изменить на одно и то же число, то в новом графе оптимальное паросочетание будет состоять из тех же ребер, что и в старом.
Доказательство:
[math]\triangleright[/math]
Полное паросочетание для каждой вершины содержит ровно одно ребро, инцидентное этой вершине. При изменении весов всех ребер, инцидентных ей, на одно и то же число, выбранное ребро останется оптимальным.
[math]\triangleleft[/math]

Далее будем рассматривать только графы с неотрицательной весовой функцией, так как, согласно этой лемме, задачу о назначениях на остальных графах можно свести к задаче о назначениях на них.

Лемма:
Выделим в множествах [math]X[/math] и [math]Y[/math] подмножества [math]X', Y'[/math]. Если прибавить ко всем весам ребер, инцидентных вершинам из [math]X[/math], прибавить, а потом от всех весов ребер, инцидентных вершинам из [math]Y[/math], отнять [math]d = \min \{c(x, y)|x \in X', y \in Y\backslash Y'\}[/math], то:
  1. веса всех ребер графа останутся неотрицательными;
  2. Веса ребер вида [math]xy[/math], где [math]x \in X', y \in Y'[/math] или [math]x \in X \backslash X', y \in Y \backslash Y'[/math], не изменятся.
Доказательство:
[math]\triangleright[/math]

Рассмотрим матрицу весов графа. Не умаляя общности, можно сказать, что множества [math] X' [/math] и [math] Y' [/math] состоят из первых элементов множеств [math] X [/math] и [math] Y [/math] соответственно (мы упорядочиваем множества по номерам вершин). Тогда вся матрица делится на 4 блока:

[math] X' [/math] [math] X \backslash X' [/math]
[math] Y' [/math] [math] A + d - d [/math] [math] B - d [/math]
[math] Y \backslash Y' [/math] [math] C + d [/math] [math] D [/math]
Веса группы [math] A [/math] будут сначала увеличены, а потом уменьшены на [math] d [/math], поэтому они не изменятся, веса группы [math] D [/math] вообще изменяться не будут. Все веса группы [math] B [/math] будут уменьшены на [math] d [/math], но [math] d [/math] - минимум среди этих весов, поэтому они останутся неотрицательными.
[math]\triangleleft[/math]
Лемма:
Если веса всех ребер графа неотрицательны и некоторое полное паросочетание состоит из ребер нулевого веса, то оно является оптимальным.
Доказательство:
[math]\triangleright[/math]
Действительно, паросочетание с какими-то другими весами ребер имеет больший вес и оптимальным не является.
[math]\triangleleft[/math]

Алгоритм

Доказанные ранее утверждения позволяют придумать схему алгоритма, решающего задачу о назначениях: нужно найти полное паросочетание из ребер нулевого веса в графе, полученном из исходного преобразованиями, описанными в первых двух леммах.

Алгоритм, решающий задачу, работает с графом, как с матрицей весов.

  1. Вычитаем из каждой строки значение ее минимального элемента. Теперь в каждой строке есть хотя бы один нулевой элемент.
  2. Вычитаем из каждого столбца значение его минимального элемента. Теперь в каждом столбце есть хотя бы один нулевой элемент.
  3. Ищем в текущем графе полное паросочетание из ребер нулевого веса:
    1. Если оно найдено, то желаемый результат достигнут, алгоритм закончен.
    2. В противном случае, покроем нули матрицы весов минимальным количеством строк и столбцов (это не что иное, как нахождение минимального контролирующего множества в двудольном графе). Теперь применим преобразование из леммы 2, взяв в качестве [math] X' [/math] и [math] Y' [/math] вершины левой и правой долей минимального контролирующего множества. Очевидно, после его выполнения в матрице весов появится новый нуль. После этого перейдем к шагу 1.

Анализ времени работы

Поиск максимального паросочетания или минимального контролирующего множества в двудольном графе совершается за [math] O(n^2) [/math] операций. При каждом повторении шагов 1-3 в матрице весов появляется новый нуль, который увеличивает размер максимального паросочетания хотя бы на 1, поэтому всего будет совершено [math] O(n) [/math] итераций внешнего цикла. Поэтому суммарная асимптотика работы данного алгоритма - [math] O(n^3) [/math].

Ссылки

Литература

  • Асанов М., Баранский В., Расин В. - Дискретная математика: Графы, матроиды, алгоритмы — 2010, 368 стр.