Пређи на садржај

Stoer-Vagnerov algoritam

С Википедије, слободне енциклопедије
Miinalni rez tezinskog grafa minimalne tezine 4.[1]

Stoer-Vagnerov algoritam u teoriji grafova predstavlja rekurzivan algoritam koji rešava problem minimalnog reza u neusmerenom težinskom grafu. Predložen je od strane Frenka Vagnera (eng. Frank Wagner) i Methild Stoera (eng. Mechthild Stoer) 1995. godine. Suštinska ideja ovog algoritma je da suzi graf spajajući čvorove najveće težine, sve dok graf ne sadrži samo dva seta kombinovanih najviših čvorova[2]. Nakon svakog suženja, težina spojenog reza se čuva u listi. Konačno rez najmanje težine u listi biće minimum grafa.

Rez predstavlja podelu čvorova grafa u dva nesrazmerna podskupa. Minimalan rez je rez čija veličina ili težina nije veća od veličine bilo kog drugog reza. Za težinski graf minimalan rez će jednostavno biti rez sa najmanjim brojem grana. Za težinski graf, zbir svih težina čvorova reza određuje da li je rez minimalan. U praksi, problem mimimalnog reza se uvek raspravlja zajedno sa problemom maksimalnog protoka jer prilikom traženja maksimalnog kapaciteta mreže minimalan rez je "usko grlo" u grafu ili mreži.

Stoer-Vagnerov algoritam minimalnog reza[уреди | уреди извор]

Neka je ( ) težinski neusmeren graf. Neka budu globalni minimalni rezovi grafa . Pretpostavimo da .

Ako onda su očigledno minimalni rez grafa .[3]

Ovaj algoritam počinje pronalaženjem minimalnog reza grafa dva temena . Par ima dve različite mogućnosti, su minimalni rez grafa ili pripadaju istoj strani minimalnog reza grafa . Dakle minimalni rez se može pronaći proveraavanjem grafa koji nastaje nakon spajanja čvorova i . Tokom spajanja, ako su i tpovezani granom, ta grana nestaje . Ako su i povezani granom sa čvorom najveće težine onda težina čvora dobija novu vrednost .[3] Algoritam se opisuje sa[2]:

  • FazaMinimalnogReza
   
   while 
       dodati u  najbliži čvor grafa
       smestiti rez-faze i smanjiti   spajanjem dva čvora koji su dodati poslednji
  • MinimalniRez
   while 
       FazaMinimalnogReza
       if rez-faze je lakši od trenutnog minimalnog reza
           then postaviti rez-faze kao trenutni minimalni rez

Algoritam radi u fazama. U fazi FazaMinimalnogReza, podskup čvorova grafa raste počevši od nekog proizvoljnog čvora dok ne bude jednako . U svakom koraku, čvor koji je van skupa , ali je usko povezan sa skupom , dodaje se tom skupu. Ovaj postupak se formalno može pokazati kao[2]: dodati čvor najveće težine tako da gde je suma težina svih grana između . Stoga u samoj fazi par čvorova i kao i minimalan rez se utvrđuje.[4] Nakon jedne faze FazaMinimalnogReza, dva čvora se spajaju u novi čvor, i grane ta dva čvora se zamenjuju novom granom čija je težina jednaka zbiru prethodne dve grane. A grane koje povezuju ove čvorove se uklanjaju. Ako postoji minimalan rez grafa odvajanjem i onda je minimalni rez grafa . Ako nije tako minimalan rez mora imati i na istoj strani. Stoga, algoritam ih spaja u jedan čvor. Pored toga MinimalniRez će se ažurirati nakon svake faze FazaMinimalnogReza. Nakon faza možemo odrediti minimalni rez.[4]

Primer[уреди | уреди извор]

Graf u koraku 1 prikazuje originalni graf i nasumično bira čvor 2 kao početni čvor za ovaj algoritam. U FazaMinimalnogReza, skup ima samo čvor 2, najteža ivica je ivica (2,3), tako da se čvor 3 dodaje u skup . Dalje, skup sadrži čvor 2 i čvor 3, najteža ivica je (3,4 ), pa se skupu dodaje čvor 4. Praćenjem ove procedure, poslednja dva čvora su čvor 5 i čvor 1, koji su s i t u ovoj fazi. Njihovim spajanjem, novi graf izgleda kao što je prikazano u koraku 2. U ovoj fazi, težina reza je 5, što je suma ivica (1,2) i (1,5). Sada, je završena prva petlja faze MinimalniRez.

U koraku 2, počevši od čvora 2, najteži ivica je (2,15), pa se čvor 15 stavlja u skup . Sledeća najteža ivica je (2,3) ili (15,6), biramo (15,6) pa se čvor 6 dodaje u skup. Onda uporedimo ivice (2,3) i (6,7) i izaberemo čvor 3 da bude stavljen u skup . Poslednja dva čvora su čvor 7 i čvor 8. Dakle, spojimo ivicu (7,8). Minimalan rez je 5, tako da minimum ostaje 5. Sledeći koraci ponavljaju iste operacije na spojeni graf, dok ne ostane samo jedna ivica na grafu, kao što je prikazano u koraku 7. Globalni minimalni rez ima ivicu (2, 3) i ivicu (6,7), što se uočava u koraku 5.

Dokaz korektnosti[уреди | уреди извор]

Da bi se dokazala ispravnost ovog algoritma, moramo dokazati da je FazaMinimalnogReza u stvari najmanji rez grafa, gde su i dva čvora koja su poslednja dodata u fazi. Dakle, lema je prikazana ispod:

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

Ovo dokazujemo indukcijom na skupu aktivnih temena. Neka je proizvoljan rez, i rez faze. Moramo pokazati da je . Primetimo da nam jedno izvršavanje faze FazaMinimalnogReza daje permutaciju svih temena u grafu (gde je prvi, a i su dva temena koja se dodaju poslednja u fazi). Dakle, mi kažemo da je čvor aktivan ako , čvor pre čvora u redosledu temena proizvodenom fazom FazaMinimalnogReza je u ili obrnuto, što će reći, da su na suprotnim stranama reza. Definišemo kao skup temena dodat u skup pre i kao rez od skupa izveden iz . Za sve aktivne čvorove :

Neka bude prvi aktivni čvor. Po definiciji sledi da su and ekvivalentni. predstavlja sve čvorove dodate u pre , i ivice između tih čvorova i su ivice koje prelaze rez C. Dakle, kao što je prikazano gore, za aktivne čvorove i ( se dodaje u pre ):

uvođenjem ,

doprinosi ali ne

Tako, pošto je uvek aktivni čvor posto poslednji rez faze odvaja od po definiciji, za bilo koji aktivni čvor :

Dakle, maksimalna težina reza faze je jednaka .

Vremenska složenost[уреди | уреди извор]

Vreme izvršavanja algoritma MinimalniRez je jednak vremenu izvršavanja faze FazaMinimalnogReza puta, koji se poziva na grafove sa smanjenjem broja čvorova i ivica. Za jedno izvršavanje faze FazaMinmalnogReza treba najviše vremena. Dakle, ukupno trajanje bi trebalo da bude proizvod dve faze kompleksnosti, koji je [2]. Za dalje poboljšanje, ključ je da se lako odabere sledeći čvor koji se dodaje u skup A, najbliži čvor. Tokom izvržavanja faze, svi čvorovi koji nisu u nalaze se u prioritetnom redu baziranom na osnovu ključne oblasti. Ključ čvora je zbir težina ivica koji ga spajaju sa trenutnim A, to jest, . Kad god se čvor dodaje u mora da se izvrši ažuriranje reda. mora da bude izbrisan iz reda, a ključ svakog čvora koji se ne nalazi u , i koji je povezan sa mora se povećati za težinu ivice , ako postoji. Pošto se ovo radi upravo jednom za svaku ivicu, ukupno moramo puta da izvršimo operaciju IzvuciMaksimum i puta operaciju PovećajKljuč. Korišćenjem Fibonačijevog hipa možemo izvršiti operaciju IzvuciMaksimum u vremenu i operaciju PovećajKljuč u vremenu. Tako, vreme potrebno za ovaj ključni korak koji dominira ostatakom faze, je .[2]

Primer koda[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;  
}

Reference[уреди | уреди извор]

Spoljašnje veze[уреди | уреди извор]

Minimalni rez (primena u računarskim mrežama)