Сам алгоритм зиждется на двух утверждениях и двух теоремах, доказательства которых здесь не приводятся, из-за их довольно большого объёма.
Для начала определимся с тем, что мы, собственно, ищем.
Пусть задано конечное множество
и семейство
его подмножеств
.
Найти подсемейство
(если оно существует) такое, что
и мощность подсемейства S* (покрытия множества V) наименьшая из всех возможных.
Следующие утверждения определяют понятия минимального и наименьшего покрытия.
Утверждение 1.
Для того чтобы подсемейство
, было покрытием множества
, необходимо и достаточно, чтобы выполнялось условие

Покрытие S’ называется минимальным, если не существует покрытия S» такого, что
.
Покрытие S* называется наименьшим, если для любого минимального покрытия S’ выполняется условие

Утверждение 2.
Покрытие
минимально тогда и только тогда, когда для любого
, выполняется условие

И, самое основное.
Пусть задано конечное множество
и семейство
его подмножеств
.
Построим полный нагруженный граф
, в котором множеству
вершин графа взаимно однозначно сопоставлено семейство
подмножеств
,
а каждому ребру
— подмножество
.
Обозначим
множество всех рёбер инцидентных вершине
, а
— множество всех вершин, инцидентных рёбрам из множества
.
Теорема 1.
Минимальное по мощности подмножество
ребер, инцидентных произвольной вершине
в графе G, при выполнении условий
определяет минимальное покрытие
, однозначно соответствующее множеству
вершин, если
, или множеству
вершин, если
.
Теорема 2.
Минимальное по мощности подмножество
ребер, инцидентных произвольной вершине
ребра
в графе G, при выполнении условий
для всех 
определяет наименьшее покрытие
, однозначно соответствующее множеству
вершин, если
, или множеству
вершин, если
.
На основании теорем предлагается следующий алгоритм поиска наименьшего покрытия.
1. Множеству
и семейству
его подмножеств
, сопоставить семейство
подмножеств
. Если для некоторого
окажется
, то существует тривиальное покрытие
. Конец алгоритма.
Иначе перейти на п.2.
2. Построить полный нагруженный граф
, где
.
Вершину
нагрузить множеством
Ребро
нагрузить множеством
.
3. Проверить существование покрытия: для произвольной вершины
определить подмножество
,
где
— множество рёбер, инцидентных вершине
в графе
.
Если
, то покрытия не существует. Конец алгоритма.
Если
, то покрытие существует. Перейти к процедуре поиска наименьшего покрытия (п. 4).
4. Положить t:=0.
5. В полном нагруженном графе
найти ребро
для которого выполняется условие
.
Если
, то перейти на п. 6,
иначе — на процедуру построения множества D вершин, определяющих наименьшее покрытие
(п. 7).
6. Построить полный нагруженный граф
, полагая
,
— множество рёбер, инцидентных вершине
в графе
.
Положить
для всех
.
Положить t:=t+1 и перейти на п. 5.
7. Начало построения множества D вершин, определяющих наименьшее покрытие
.
Положить
.
8. Если t=0, то перейти на п. 11, иначе — положить t:=t-1.
9. В графе
определить подмножество 
10. Если в графе
выполняется условие
, то положить
, иначе — D:=D. Перейти на п. 8.
11. Семейство
подмножеств
определяет наименьшее покрытие множеств
.
Конец алгоритма.
Попробуем оценить сложность алгоритма.
Вся, так сказать, суть алгоритма (с точки зрения оценки сложности) заключена в фразе «построим полный нагруженный граф».
Нам требуется выполнить n действий для вычисления нагрузки в n вершинах графа и (n-1)n/2 вычислений (по количеству рёбер полного графа) для нагрузки рёбер графа. И всё это, если рассматривать наихудший случай, когда подмножества взаимно не пересекаются, выполняется n-2 раза. Таким образом грубая оценка O(n) = n3 + n2.
И в заключение. Не уверен, что пост заслуживает инвайта, потому как моя причастность к алгоритму более чем сомнительная. Но опубликования, как мне кажется, стоит. Надеюсь модераторы разберутся.
Как там греки говорили? — Fais se que dois adviegne que peut (делай, что должно, и будь, что будет).
(или это были римляне?)
ссылка на оригинал статьи http://habrahabr.ru/post/225831/
Добавить комментарий