Алгоритм Стоера – Вагнера

В теории графов алгоритм Штера – Вагнера представляет собой рекурсивный алгоритм для решения задачи минимального разреза в неориентированных взвешенных графах с неотрицательными весами. Он был предложен Мехтильдом Стером и Франком Вагнером в 1995 году. Основная идея этого алгоритма состоит в том, чтобы сжать граф путем слияния наиболее интенсивных вершин до тех пор, пока граф не будет содержать только два объединенных набора вершин. [ 2 ] На каждом этапе алгоритм находит минимум - разрезать на две вершины и выбран по своему желанию. Затем алгоритм сужает грань между и искать не - порезы. Минимальный разрез, найденный на всех этапах, будет минимально взвешенным разрезом графа.
Разрез — это разбиение вершин графа на два непустых, непересекающихся подмножества. Минимальный отруб – это отруб, размер или вес которого не превышает размер любого другого отруба. Для невзвешенного графа минимальным разрезом будет просто разрез с наименьшим количеством ребер. Для взвешенного графа сумма весов всех ребер на разрезе определяет, является ли этот разрез минимальным. На практике проблема минимального разреза всегда обсуждается вместе с проблемой максимального потока , чтобы исследовать максимальную пропускную способность сети , поскольку минимальный разрез является узким местом в графе или сети.
Алгоритм минимального разреза Штера – Вагнера
[ редактировать ]Позволять быть взвешенным неориентированным графом. Предположим, что . Разрез называется - вырезать, если ровно один из или находится в . Минимальный разрез это тоже - разрез называется - минимальная версия . [ 3 ]
Этот алгоритм начинается с поиска и в и сокращение на первую минуту из . Для любой пары , возможны две ситуации: либо представляет собой глобальную минимальную версию , или и принадлежат к одной и той же стороне глобального минимального разреза . Следовательно, глобальный минимальный разрез можно найти, проверив график , который представляет собой граф после слияния вершин и в новую вершину . При слиянии, если и соединены ребром, то это ребро исчезает. Если и оба имеют ребра к некоторой вершине , то вес ребра из новой вершины к является . [ 3 ] Алгоритм описывается как: [ 2 ]
MinimumCutPhase while add to the most tightly connected vertex end store the cut in which the last remaining vertex is by itself (the "cut-of-the-phase") shrink by merging the two vertices (s, t) added last (the value of "cut-of-the-phase" is the value of minimum s, t cut.) MinimumCut while MinimumCutPhase if the cut-of-the-phase is lighter than the current minimum cut then store the cut-of-the-phase as the current minimum cut
Алгоритм работает поэтапно. В MinimalCutPhase подмножество вершин графов растет, начиная с произвольной одиночной вершины, до тех пор, пока равно . На каждом шаге вершина, находящаяся за пределами , но наиболее тесно связан с добавляется в набор . Формально эту процедуру можно представить так: [ 2 ] добавить вершину такой, что , где представляет собой сумму весов всех ребер между и . Итак, за одну фазу пара вершин и , и минута резать определяется. [ 4 ] После одного этапа МинимальногоCutPhase две вершины объединяются в новую вершину, а ребра от двух вершин до оставшейся вершины заменяются ребром, взвешенным по сумме весов двух предыдущих ребер. Ребра, соединяющие объединенные узлы, удаляются. Если существует минимальный разрез разделяющий и , это минимальный разрез . Если нет, то минимальный разрез должен иметь и на той же стороне. Следовательно, алгоритм объединит их в один узел. Кроме того, «Минимальный разрез» будет записывать и обновлять глобальный минимальный разрез после каждой «Минимальной фазы разреза». После фаз, минимальный разрез . можно определить [ 4 ]
Пример
[ редактировать ]Этот раздел относится к рис. 1–6 в оригинальной статье. [ 2 ]
График на шаге 1 показывает исходный график. и случайным образом выбирает узел 2 в качестве начального узла для этого алгоритма. В МинимальнойCutPhase установите имеет только узел 2, самое тяжелое ребро — это ребро (2,3), поэтому узел 3 добавляется в набор . Далее установите содержит узел 2 и узел 3, самое тяжелое ребро — (3,4), поэтому узел 4 добавляется в набор . Следуя этой процедуре, последние два узла — это узел 5 и узел 1, которые и на этом этапе. Объединив их в узел 1+5, новый граф будет таким, как показано на шаге 2. На этом этапе вес разреза равен 5, что представляет собой сумму ребер (1,2) и (1,5). На данный момент первый цикл MiniCut завершен.
На шаге 2, начиная с узла 2, самое тяжелое ребро — (2,1+5), поэтому узел 1+5 помещается в набор. . Следующие самые тяжелые ребра — (2,3) или (1+5,6), мы выбираем (1+5,6), таким образом к набору добавляется узел 6. Затем мы сравниваем ребро (2,3) и (6,7) и выбираем узел 3, чтобы поместить его в набор . Последние два узла — это узел 7 и узел 8. Поэтому объедините ребро (7,8). Минимальное сокращение — 5, поэтому оставьте минимальное значение равным 5.
Следующие шаги повторяют те же операции над объединенным графом, пока в графе не останется только одно ребро, как показано на шаге 7. Глобальный минимальный разрез имеет ребро (2,3) и ребро (6,7), которое обнаруживается. на шаге 5.
Доказательство правильности
[ редактировать ]Чтобы доказать правильность этого алгоритма, нам нужно доказать, что разрез, заданный MinimalCutPhase, на самом деле является минимальным. разрез графа, где s и t — две вершины, добавленные последними на этапе. Поэтому ниже показана лемма:
Лемма 1 : МинимумCutPhase возвращает минимум. -вырезка .
Позволять быть произвольным вырезать, и быть разрезом, заданным фазой. Мы должны показать, что . Обратите внимание, что один запуск MiniminCutPhase дает нам упорядочивание всех вершин графа (где является первым и и две вершины, добавленные последними в фазе). Мы говорим вершина активен, если и вершина, добавленная непосредственно перед являются в противоположных сторонах разреза. Докажем лемму индукцией по множеству активных вершин. Мы определяем как набор вершин, добавленных к до , и быть множеством ребер в оба конца в , то есть разрез, вызванный . Докажем, что для каждой активной вершины ,
Позволять быть первой активной вершиной. По определению этих двух величин, и эквивалентны. это просто все вершины, добавленные в до , а ребра между этими вершинами и это края, которые пересекают разрез . Поэтому, как показано выше, для активных вершин и , с добавлено в до :
по индукции,
с способствует но не для того (и другие ребра имеют неотрицательный вес)
Таким образом, поскольку всегда является активной вершиной, поскольку последний разрез фазы отделяется от по определению для любой активной вершины :
Поэтому срез фазы не более чем такой же тяжелый, как .
Временная сложность
[ редактировать ]Время работы алгоритма «МинимумКут» равно добавленному времени работы алгоритма « МинимумКут». запускаетминимальнуюCutPhase , которая вызывается на графах с уменьшающимся количеством вершин и ребер.
Для MinimalCutPhase для одного запуска требуется не более время.
Следовательно, общее время работы должно быть произведением двухфазной сложности, которая равна . [ 2 ]
Ключом к дальнейшему улучшению является упрощение выбора следующей вершины, добавляемой в набор. , наиболее тесно связанная вершина. Во время выполнения фазы все вершины, не находящиеся в находиться в приоритетной очереди на основе ключевого поля. Ключ вершины представляет собой сумму весов ребер, соединяющих его с током , то есть, . Всякий раз, когда вершина добавляется в нам нужно выполнить обновление очереди. необходимо удалить из очереди, а ключ каждой вершины не в , подключен к необходимо увеличить на вес кромки , если он существует. Поскольку это делается ровно один раз для каждого ребра, в целом нам придется выполнить ExtractMax и Операции увеличения клавиш. Используя кучу Фибоначчи, мы можем выполнить операцию ExtractMax в амортизированное время и операция EnhanceKey в амортизированное время. Таким образом, время, необходимое нам для этого ключевого шага, который доминирует над остальной частью фазы, равно . [ 2 ]
Пример кода
[ редактировать ]Ниже приведена краткая на C++ . реализация алгоритма Штера – Вагнера [ 5 ]
// Adjacency matrix implementation of Stoer–Wagner min cut algorithm.
//
// Running time:
// O(|V|^3)
#include <bits/stdc++.h>
using namespace std;
pair<int, vector<int>> globalMinCut(vector<vector<int>> mat) {
pair<int, vector<int>> best = {INT_MAX, {}};
int n = mat.size();
vector<vector<int>> co(n);
for (int i = 0; i < n; i++)
co[i] = {i};
for (int ph = 1; ph < n; ph++) {
vector<int> w = mat[0];
size_t s = 0, t = 0;
for (int it = 0; it < n - ph; it++) { // O(V^2) -> O(E log V) with prio. queue
w[t] = INT_MIN;
s = t, t = max_element(w.begin(), w.end()) - w.begin();
for (int i = 0; i < n; i++) w[i] += mat[t][i];
}
best = min(best, {w[t] - mat[t][t], co[t]});
co[s].insert(co[s].end(), co[t].begin(), co[t].end());
for (int i = 0; i < n; i++) mat[s][i] += mat[t][i];
for (int i = 0; i < n; i++) mat[i][s] = mat[s][i];
mat[0][t] = INT_MIN;
}
return best;
}
[ нужна ссылка ]
const int maxn = 550;
const int inf = 1000000000;
int n, r;
int edge[maxn][maxn], dist[maxn];
bool vis[maxn], bin[maxn];
void init()
{
memset(edge, 0, sizeof(edge));
memset(bin, false, sizeof(bin));
}
int contract( int &s, int &t ) // Find s,t
{
memset(dist, 0, sizeof(dist));
memset(vis, false, sizeof(vis));
int i, j, k, mincut, maxc;
for (i = 1; i <= n; i++)
{
k = -1; maxc = -1;
for (j = 1; j <= n; j++)if (!bin[j] && !vis[j] && dist[j] > maxc)
{
k = j; maxc = dist[j];
}
if (k == -1) return mincut;
s = t; t = k;
mincut = maxc;
vis[k] = true;
for (j = 1; j <= n; j++) if (!bin[j] && !vis[j])
dist[j] += edge[k][j];
}
return mincut;
}
int Stoer_Wagner()
{
int mincut, i, j, s, t, ans;
for (mincut = inf, i = 1; i < n; i++)
{
ans = contract(s, t);
bin[t] = true;
if (mincut > ans) mincut = ans;
if (mincut == 0) return 0;
for (j = 1; j <= n; j++) if (!bin[j])
edge[s][j] = (edge[j][s] += edge[j][t]);
}
return mincut;
}
Ссылки
[ редактировать ]- ^ «Библиотека графов повышения: Min-Cut Стера – Вагнера - 1.46.1» . www.boost.org . Проверено 7 декабря 2015 г.
- ^ Перейти обратно: а б с д и ж «Простой алгоритм минимального сокращения» .
- ^ Перейти обратно: а б «Конспекты лекций по анализу алгоритмов»: Глобальные минимальные сокращения» (PDF) .
- ^ Перейти обратно: а б «Алгоритм минимального разреза Штера и Вагнера» (PDF) .
- ^ «Библиотека шаблонов соревнований по алгоритмам KTH» . github.com . Проверено 17 ноября 2021 г.
Внешние ссылки
[ редактировать ]- StoerWagnerMinCut.java — библиотека Java, реализующая алгоритм Штера – Вагнера.