Стоер-Вагнеров алгоритам

Стоер-Вагнеров алгоритам у теорији графова представља рекурзиван алгоритам који решава проблем минималног реза у неусмереном тежинском графу. Предложен је од стране Френка Вагнера (енг. Франк Wагнер) и Метхилд Стоера (енг. Мецхтхилд Стоер) 1995. године. Суштинска идеја овог алгоритма је да сузи граф спајајући чворове највеће тежине, све док граф не садржи само два сета комбинованих највиших чворова[2]. Након сваког сужења, тежина спојеног реза се чува у листи. Коначно рез најмање тежине у листи биће минимум графа.

Миинални рез тезинског графа минималне тезине 4.[1]

Рез представља поделу чворова графа у два несразмерна подскупа. Минималан рез је рез чија величина или тежина није већа од величине било ког другог реза. За тежински граф минималан рез ће једноставно бити рез са најмањим бројем грана. За тежински граф, збир свих тежина чворова реза одређује да ли је рез минималан. У пракси, проблем мимималног реза се увек расправља заједно са проблемом максималног протока јер приликом тражења максималног капацитета мреже минималан рез је "уско грло" у графу или мрежи.

Стоер-Вагнеров алгоритам минималног реза уреди

Нека је     (   ) тежински неусмерен граф. Нека   буду глобални минимални резови графа  . Претпоставимо да  .

Ако   онда су  очигледно   минимални рез графа  .[3]

Овај алгоритам почиње проналажењем   минималног реза   графа   два темена     . Пар   има две различите могућности,   су минимални рез графа   или припадају истој страни минималног реза графа  . Дакле минимални рез се може пронаћи провераавањем графа   који настаје након спајања чворова   и  . Током спајања, ако су   и   тповезани граном, та грана нестаје . Ако су   и   повезани граном са чвором највеће тежине онда тежина чвора добија нову вредност   .[3] Алгоритам се описује са[2]:

  • ФазаМинималногРеза 
    
   while  
       dodati u   najbliži čvor grafa
       smestiti rez-faze i smanjiti    spajanjem dva čvora koji su dodati poslednji
  • МинималниРез 
   while  
       FazaMinimalnogReza 
       if rez-faze je lakši od trenutnog minimalnog reza
           then postaviti rez-faze kao trenutni minimalni rez

Алгоритам ради у фазама. У фази ФазаМинималногРеза, подскуп   чворова графа расте почевши од неког произвољног чвора док   не буде једнако  . У сваком кораку, чвор који је ван скупа  , али је уско повезан са скупом  , додаје се том скупу. Овај поступак се формално може показати као[2]: додати чвор највеће тежине   тако да   где је   сума тежина свих грана између  . Стога у самој фази пар чворова   и   као и минималан   рез   се утврђује.[4] Након једне фазе ФазаМинималногРеза, два чвора се спајају у нови чвор, и гране та два чвора се замењују новом граном чија је тежина једнака збиру претходне две гране. А гране које повезују ове чворове се уклањају. Ако постоји минималан рез графа   одвајањем   и   онда је   минимални рез графа  . Ако није тако минималан рез   мора имати   и   на истој страни. Стога, алгоритам их спаја у један чвор. Поред тога МинималниРез ће се ажурирати након сваке фазе ФазаМинималногРеза. Након   фаза можемо одредити минимални рез.[4]

Пример уреди

Граф у кораку 1 приказује оригинални граф   и насумично бира чвор 2 као почетни чвор за овај алгоритам. У ФазаМинималногРеза, скуп   има само чвор 2, најтежа ивица је ивица (2,3), тако да се чвор 3 додаје у скуп  . Даље, скуп   садржи чвор 2 и чвор 3, најтежа ивица је (3,4 ), па се скупу   додаје чвор 4. Праћењем ове процедуре, последња два чвора су чвор 5 и чвор 1, који су с и т у овој фази. Њиховим спајањем, нови граф изгледа као што је приказано у кораку 2. У овој фази, тежина реза је 5, што је сума ивица (1,2) и (1,5). Сада, је завршена прва петља фазе МинималниРез.

У кораку 2, почевши од чвора 2, најтежи ивица је (2,15), па се чвор 15 ставља у скуп  . Следећа најтежа ивица је (2,3) или (15,6), бирамо (15,6) па се чвор 6 додаје у скуп. Онда упоредимо ивице (2,3) и (6,7) и изаберемо чвор 3 да буде стављен у скуп  . Последња два чвора су чвор 7 и чвор 8. Дакле, спојимо ивицу (7,8). Минималан рез је 5, тако да минимум остаје 5. Следећи кораци понављају исте операције на спојени граф, док не остане само једна ивица на графу, као што је приказано у кораку 7. Глобални минимални рез има ивицу (2, 3) и ивицу (6,7), што се уочава у кораку 5.

Доказ коректности уреди

Да би се доказала исправност овог алгоритма, морамо доказати да је ФазаМинималногРеза у ствари најмањи   рез графа, где су   и   два чвора која су последња додата у фази. Дакле, лема је приказана испод:

 Lema 1: FazaMinimalnogReza vraća minimalni  -rez grafa  .

Ово доказујемо индукцијом на скупу активних темена. Нека је   произвољан   рез, и   рез фазе. Морамо показати да је  . Приметимо да нам једно извршавање фазе ФазаМинималногРеза даје пермутацију свих темена у графу (где је   први, а   и   су два темена која се додају последња у фази). Дакле, ми кажемо да је чвор   активан ако  , чвор пре чвора   у редоследу темена производеном фазом ФазаМинималногРеза је у   или обрнуто, што ће рећи, да су на супротним странама реза. Дефинишемо   као скуп темена додат у скуп   пре   и   као рез од скупа   изведен из  . За све активне чворове  :

 

Нека   буде први активни чвор. По дефиницији следи да су   анд   еквивалентни.   представља све чворове додате у   пре  , и ивице између тих чворова и   су ивице које прелазе рез C. Дакле, као што је приказано горе, за активне чворове   и   (  се додаје у   пре  ):

 

  увођењем ,  

    доприноси   али не  

Тако, пошто је   увек активни чвор посто последњи рез фазе одваја   од   по дефиницији, за било који активни чвор  :

 

Дакле, максимална тежина реза фазе је једнака  .

Временска сложеност уреди

Време извршавања алгоритма МинималниРез је једнак времену извршавања фазе ФазаМинималногРеза   пута, који се позива на графове са смањењем броја чворова и ивица. За једно извршавање фазе ФазаМинмалногРеза треба највише   времена. Дакле, укупно трајање би требало да буде производ две фазе комплексности, који је  [2]. За даље побољшање, кључ је да се лако одабере следећи чвор који се додаје у скуп А, најближи чвор. Током извржавања фазе, сви чворови који нису у   налазе се у приоритетном реду базираном на основу кључне области. Кључ чвора   је збир тежина ивица који га спајају са тренутним А, то јест,  . Кад год се чвор   додаје у   мора да се изврши ажурирање реда.   мора да буде избрисан из реда, а кључ сваког чвора   који се не налази у  , и који је повезан са   мора се повећати за тежину ивице  , ако постоји. Пошто се ово ради управо једном за сваку ивицу, укупно морамо   пута да извршимо операцију ИзвуциМаксимум и   пута операцију ПовећајКључ. Коришћењем Фибоначијевог хипа можемо извршити операцију ИзвуциМаксимум у   времену и операцију ПовећајКључ у   времену. Тако, време потребно за овај кључни корак који доминира остатаком фазе, је  .[2]

Пример кода[5] уреди

// Implementacija Stoer-Vagnerovog algoritma preko matrice povezanosti
//
// Vreme izvršavanja:
// O(|V|^3)
//
// ULAZ:
// - graf, konstruisan korišćenjem DodajIvicu()
// IZLAZ:
// - (vrednost minimalnog reza, polovina čvorova u minimalnom rezu)
#include <cmath>
#include <vector>
#include <iostream>

using namespace std;

typedef vector<int> VI;
typedef vector<VI> VVI;

const int INF = 1000000000;

pair<int, VI> NadjiMinimalniRez(VVI &težine) {
  int N = težine.veličina();
  VI koriščen(N), rez, najbolji_rez;
  int najbolja_težina = -1;
  
  for (int faza = N-1; faza >= 0; faza--) {
    VI w = težine[0];
    VI dodati = korišćen;
    int prethodni, poslednji = 0;
    for (int i = 0; i < faza; i++) {
      prethodni = poslednji;
      poslednji = -1;
      for (int j = 1; j < N; j++)
	if (!dodati[j] && (poslednji == -1 || w[j] > w[poslednji])) poslednji = j;
      if (i == faza-1) {
	for (int j = 0; j < N; j++) težine[prethodni][j] += težine[poslednji][j];
	for (int j = 0; j < N; j++) težine[j][prethodni] = težine[prethodnji][j];
	korišćen[poslednji] = true;
	cut.push_back(poslednji);
	if (najbolja_težina == -1 || w[poslednji] < najbolja_težina) {
	 najbolji_rez = rez;
	 najbolja_težina = w[poslednji];
	}
      } else {
	for (int j = 0; j < N; j++)
	 w[j] += težine[poslednji][j];
	dodati[poslednji] = true;
      }
    }
  }
  return napravi_par(najbolja_težina, najbolji_rez);
}


const int maxn = 550;
const int inf = 1000000000;
int n, r;
int ivica[maxn][maxn], dist[maxn];
bool vis[maxn], bin[maxn];
void init()
{
    memset(ivica, 0, sizeof(ivica));  
    memset(bin, false, sizeof(bin));  
}
int contract( int &s, int &t ) // Naći s,t
{
    memset(dist, 0, sizeof(dist));  
    memset(vis, false, sizeof(vis));  
    int i, j, k, min_rez, 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 min_rez;  
        s = t;  t = k;  
        min_rez = maxc;  
        vis[k] = true;  
        for(j = 1; j <= n; j++)if(!bin[j] && !vis[j])  
            dist[j] += ivica[k][j];  
    }  
    return min_rez;  
}
int Stoer_Vagner()
{
    int min_rez, i, j, s, t, ans;  
    for(min_rez = inf, i = 1; i < n; i++)  
    {  
        ans = contract( s, t );  
        bin[t] = true;  
        if(min_rez > ans)min_rez = ans;  
        if(min_rez == 0)return 0;  
        for(j = 1; j <= n; j++)if(!bin[j])  
            ivica[s][j] = (ivica[j][s] += ivica[j][t]);  
    }  
    return min_rez;  
}

Референце уреди

Спољашње везе уреди

Минимални рез (примена у рачунарским мрежама)