Grafovski algoritmi - čas 4 Artikulacione tačke i mostovi Ukoliko u neusmerenom povezanom grafu G = (V, E) postoji čvor v V takav da njegovim uklanjan

Слични документи
Microsoft Word - AIDA2kolokvijumRsmerResenja.doc

Grafovi 1. Posmatrajmo graf prikazan na slici sa desne strane. a) Odrediti skup čvorova V i skup grana E posmatranog grafa. Za svaku granu posebno odr

Algoritmi

Postavka 2: Osnovni graf algoritmi 1 DISTRIBUIRANI ALGORITMI I SISTEMI Iz kursa CSCE 668 Proleće 2014 Autor izvorne prezentacije: Prof. Jennifer Welch

1. Apsolutni pobednik na glasanju vreme memorija ulaz izlaz 0,1 s 64 Mb standardni ulaz standardni izla Apsolutni pobednik izbora je onaj ko osvoji ba

Microsoft PowerPoint - 07-DinamickeStrukturePodataka

Konstrukcija i analiza algoritama vežbe 10 Nina Radojičić 15. decembar Algoritamske strategije - podeli pa vladaj (divide and conquer) Ova stra

P11.3 Analiza zivotnog veka, Graf smetnji

P9.1 Dodela resursa, Bojenje grafa

DFS, BFS - primene 1. Dat je usmeren aciklički graf. Odštampati sva topološka uređenja. Na primer, mogući topološki redosledi su: 7, 5, 3, 1, 4, 2, 0,

1 Konusni preseci (drugim rečima: kružnica, elipsa, hiperbola i parabola) Definicija 0.1 Algebarska kriva drugog reda u ravni jeste skup tačaka opisan

Орт колоквијум

Microsoft PowerPoint - 03-Slozenost [Compatibility Mode]

Програмирај!

JMBAG IME I PREZIME BROJ BODOVA 1. (ukupno 6 bodova) MJERA I INTEGRAL 1. kolokvij 4. svibnja (Knjige, bilježnice, dodatni papiri i kalkulatori n

Државно такмичење године 5. и 6. разред 1. [pločice] Правоугаону терасу димензија d s центиметара квадратних треба поплочати коришћењем плочица

Microsoft PowerPoint - C-4-1

Programski jezici i strukture podataka 2018/2019. Programski jezici i strukture podataka Računarske vežbe vežba 10 Zimski semestar 2018/2019. Studijsk

Талесова 1 теорема и примене - неки задаци из збирке Дефинициjа 1: Нека су a и b две дужи чиjе су дужине изражене преко мерне jединице k > 0, тако да

Problemi zadovoljavanja ogranicenja.

Classroom Expectations

6-8. ČAS Celobrojno programiranje Rešavamo sledeći poblem celobrojnog programiranja: Gde pretpostavljamo da je A celobrojna matrica dimenzije,. Takođe

Konstrukcija i analiza algoritama Nina Radojičić februar Analiza algoritama, rekurentne relacije 1 Definicija: Neka su f i g dve pozitivne fun

Maksimalni protok kroz mrežu - Ford-Fulkerson, Edmonds-Karp

Рачунарска интелигенција

Microsoft PowerPoint - Ekoloska (city) logistika 8.3

P1.1 Analiza efikasnosti algoritama 1

Celobrojno programiranje Rešavamo sledeći poblem celobrojnog programiranja: min c T x Ax = b x 0 x Z n Gde pretpostavljamo da je A celobrojna matrica

Drveta odlucivanja - algoritmi

ТРОУГАО БРЗИНА и математичка неисправност Лоренцове трансформације у специјалној теорији релативности Александар Вукеља www.

Algoritmi SŠ P1

Орт колоквијум

Grananje u programu predavač: Nadežda Jakšić

JMBAG IME I PREZIME BROJ BODOVA MJERA I INTEGRAL 2. kolokvij 29. lipnja (Knjige, bilježnice, dodatni papiri i kalkulatori nisu dozvoljeni!) 1. (

Funkcije predavač: Nadežda Jakšić

РЕПУБЛИКА СРПСКА МИНИСТАРСТВО ПРОСВЈЕТЕ И КУЛТУРЕ РЕПУБЛИЧКИ ПЕДАГОШКИ ЗАВОД Милоша Обилића 39 Бањалука, Тел/факс 051/ , 051/ ; p

Microsoft Word - 15ms261

PowerPoint Presentation

ELEKTROTEHNIČKI FAKULTET, UNIVERZITET U BEOGRADU KATEDRA ZA ELEKTRONIKU UVOD U ELEKTRONIKU - 13E041UE LABORATORIJSKA VEŽBA Primena mikrokontrolera

1. Vremensko ograničenje Memorijsko ograničenje ulaz izlaz 0,1 s 64 MB standardni ulaz standardni izlaz Banka želi da upozori kupce na sumnjive aktivn

I grupa 1. Napisati program koji izračunava i ispisuje zbir 4 najveća od pet brojeva unetih sa standardnog ulaza. ulaz izlaz Analiza: 1.

08 RSA1

Tutoring System for Distance Learning of Java Programming Language

Funkcije predavač: Nadežda Jakšić

Računarski praktikum I - Vježbe 11 - Funktori

2015_k2_z12.dvi

Profajliranje ivica: Knutov algoritam i njegova unapredenja Seminarski rad u okviru kursa Verifikacija softvera Matematički fakultet Nevena Nikolić, 1

SVEUČILIŠTE U ZAGREBU PRIRODOSLOVNO MATEMATIČKI FAKULTET MATEMATIČKI ODSJEK Ivana Šore REKURZIVNOST REALNIH FUNKCIJA Diplomski rad Voditelj rada: doc.

Електротехнички факултет Универзитета у Београду Катедра за рачунарску технику и информатику Kолоквијум из Интелигентних система Колоквију

Slide 1

Microsoft PowerPoint - 13-Funkcije_2.ppt [Compatibility Mode]

PowerPoint Presentation

UNIVERZITET U NIŠU PRIRODNO MATEMATIČKI FAKULTET DEPARTMAN ZA RAČUNARSKE NAUKE Algoritmi za determinizaciju i minimizaciju nedeterminističkih automata

Microsoft Word - 13pavliskova

ПРИРОДА И ЗНАК РЕШЕЊА 2 b ax bx c 0 x1 x2 2 D b 4ac a ( сви задаци су решени) c b D xx 1 2 x1/2 a 2a УСЛОВИ Решења реална и различита D>0 Решења реалн

PRIRODNO MATEMATIČKI FAKULTET U NIŠU DEPARTMAN ZA RAČUNARSKE NAUKE Utorak, godine PRIJEMNI ISPIT IZ INFORMATIKE 1. Koja od navedenih ekste

Microsoft Word - 1.Operacije i zakoni operacija

I колоквијум из Основа рачунарске технике I СИ- 2017/2018 ( ) Р е ш е њ е Задатак 1 Тачка А Потребно је прво пронаћи вредности функција f(x

Univerzitet u Novom Sadu Tehnički fakultet Mihajlo Pupin Zrenjanin Seminarski rad Predmet: Konkuretno programiranje doc. dr Dejan Lacmanovic Zorica Br

Microsoft Word - ASIMPTOTE FUNKCIJA.doc

P2.1 Projektovanje paralelnih algoritama 1

Analiticka geometrija

СТРАХИЊА РАДИЋ КЛАСИФИКАЦИJА ИЗОМЕТРИJА И СЛИЧНОСТИ Према књизи [1], свака изометриjа σ се може представити ком позици - jом неке транслациjе за векто

JMBAG IME I PREZIME BROJ BODOVA MJERA I INTEGRAL završni ispit 6. srpnja (Knjige, bilježnice, dodatni papiri i kalkulatori nisu dozvoljeni!) 1.

Teorija skupova - blog.sake.ba

Postavka 12: Uzročnost 1 DISTRIBUIRANI ALGORITMI I SISTEMI Iz kursa CSCE 668 Proleće 2014 Autor izvorne prezentacije: Prof. Jennifer Welch

Microsoft Word - ETH2_EM_Amperov i generalisani Amperov zakon - za sajt

Microsoft Word - 4.Ucenik razlikuje direktno i obrnuto proporcionalne velicine, zna linearnu funkciju i graficki interpretira n

MIP-heuristike (Matheuristike) Hibridi izmedu metaheurističkih i egzaktnih metoda Tatjana Davidović Matematički institut SANU

VEŽBE IZ OPERACIONIH ISTRAŽIVANJA

Орт колоквијум

Inženjering informacionih sistema

OSNOVNA ŠKOLA, VI RAZRED MATEMATIKA

(Microsoft Word - Dr\236avna matura - studeni osnovna razina - rje\232enja)

Skripte2013

Microsoft PowerPoint - 10-Jednodimenzionalni nizovi.ppt [Compatibility Mode]

MAT KOL (Banja Luka) ISSN (p), ISSN (o) Vol. XX (2)(2014), PELLOVA JEDNAČINA I PITAGORIN

PROGRAMIRANJE Program je niz naredbi razumljivih računalu koje rješavaju neki problem. Algoritam je postupak raščlanjivanja problema na jednostavnije

DISKRETNA MATEMATIKA

Microsoft Word - GRAFICI TRIGONOMETRIJSKIH FUNKCIJA-II deo.doc

Model podataka

Popularna matematika

Računarski praktikum I - Vježbe 07 - Podstrukture, const, reference

Uvod u računarstvo 2+2

LAB PRAKTIKUM OR1 _ETR_

ЕНЕРГЕТСКИ ПРЕТВАРАЧИ септембар 2005

Oblikovanje i analiza algoritama 5. predavanje Saša Singer web.math.pmf.unizg.hr/~singer PMF Matematički odsjek, Zagreb OAA 2017, 5. pr

МАТЕМАТИЧКА ГИМНАЗИЈА У БЕОГРАДУ МАТУРСКИ РАД из математике ТЕОРИЈА СКУПОВА ментор: Славко Моцоња ученик: Матија Срећковић, IVБ Београд, јун 2015.

The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature opti

Analiticka geometrija

KDP

Trougao Bilo koje tri nekolinearne tačke određuju tacno jednu zatvorenu izlomljenu liniju. Trougaona linija je zatvorena izlomljena linija određena sa

P3.2 Paralelno programiranje 2

Microsoft PowerPoint - jkoren10.ppt

Техничко решење: Софтвер за симулацију стохастичког ортогоналног мерила сигнала, његовог интеграла и диференцијала Руководилац пројекта: Владимир Вуји

Microsoft Word - Ispitivanje toka i grafik funkcije V deo

ALGEBRA I (2010/11)

POSLOVNI INFORMACIONI SISTEMI I RA^UNARSKE

1 Polinomi jedne promenljive Neka je K polje. Izraz P (x) = a 0 + a 1 x + + a n x n = n a k x k, x K, naziva se algebarski polinom po x nad poljem K.

(Microsoft Word - Dr\236avna matura - rujan osnovna razina - rje\232enja)

Транскрипт:

Grafovski algoritmi - čas 4 Artikulacione tačke i mostovi Ukoliko u neusmerenom povezanom grafu G = (V, E) postoji čvor v V takav da njegovim uklanjanjem graf prestaje da bude povezan, onda takav čvor nazivamo artikulacionom tačkom (eng. articulation point, cut vertex). Na primer, ukoliko bismo u grafu sa slike 1 uklonili čvor C (zajedno sa svim granama koje su mu susedne) preostali graf ne bi ostao povezan, te je čvor C artikulaciona tačka ovog grafa. Slika 1: Primer grafa koji sadrži artikulacionu tačku C. Ako u povezanom grafu postoji grana čijim uklanjanjem iz grafa on prestaje da bude povezan, ovakvu granu nazivamo most (eng. bridge, cut edge). Na primer, ukoliko bismo u grafu na slici 2 uklonili granu CD ili granu DE graf bi prestao da bude povezan, te ove dve grane, svaka za sebe, čine most. Slika 2: Primer grafa koji sadrži most. Direktan način da u datom grafu pronađemo artikulacionu tačku podrazumeva da po jedan čvor uklanjamo iz grafa i da proveravamo da li je dobijeni graf nepovezan (npr. korišćenjem DFS algoritma). Složenost ovog algoritma je O( V ( V + E )). 1

Analogno, mostove u datom grafu bismo mogli da odredimo uklanjanjem po jedne grane iz grafa i proverom da li graf ostaje povezan. Složenost ovog algoritma je O( E ( V + E )). Postoje i efikasniji algoritmi za određivanje artikulacionih tačaka i mostova u grafu. Mi ćemo u nastavku razmotriti algoritme koje su osmislili Tardžan i Hopkroft i koji su linearne vremenske složenosti. S obzirom na to da je algoritam za pronalaženje mostova donekle jednostavniji, krenućemo od njega. Važi sledeće tvrđenje: svaka grana (u, v) grafa koja ne pripada nekom ciklusu je most (jer nakon izbacivanja grane (u, v) ne postoji način kako doći od čvora u do čvora v). Specijalno, ako je graf šuma, onda je svaka grana u tom grafu most. Razmotrimo DFS drvo dobijeno DFS obilaskom datog grafa. S obzirom na to da je polazni graf neusmeren, postoje dve vrste grana u odnosu na DFS drvo: grane DFS drveta i grane koje povezuju potomka sa pretkom u odnosu na DFS drvo. Ako grana (u, v) povezuje potomka sa pretkom ona ne može biti most u grafu jer se granama DFS drveta može stići od čvora u do čvora v. Za granu (u, v) DFS drveta važi da je most ako njenim uklanjanjem graf postaje nepovezan, tj poddrvo sa korenom u v ostaje nepovezano sa delom grafa iznad ove grane. To će važiti ako ne postoji način da se (nekom granom od potomka ka pretku) stigne do čvora u ili pretka čvora u iz podgrafa sa korenom v. Kako ovo utvrditi? Za svaki čvor v potrebno je odrediti vrednost pri dolaznoj numeraciji v.p re i najmanju među vrednostima dolazne numeracije čvorova do kojih se može stići iz proizvoljnog čvora poddrveta sa korenom v označimo tu vrednost sa v.minp re (eng. low link). Važi: v.minp re = min{v.p re, u.p re, gde je u predak čvora v u DFS drvetu i postoji grana koja povezuje nekog potomka čvora v sa čvorom u. Poddrvo sa korenom v ostaće nepovezano sa delom grafa iznad ove grane ako bude važilo v.minp re u.p re. Dakle, uslov koji grana (u, v) treba da zadovoljava da bi bila most je da važi v.minp re u.p re. Tokom DFS pretrage datog neusmerog grafa, prolasku svake grane (u, v) pridružujemo neku akciju: ako je u pitanju grana koja povezuje potomka u sa pretkom v, onda ako je vrednost v.p re manja od tekuće vrednosti u.minp re, vrednost u.minp re postavljamo na v.p re ako je u pitanju grana DFS drveta, onda čvoru v postavljamo vrednost v.p re, vrednost v.minp re inicijalizujemo na v.p re, a nakon rekurzivne obrade kompletnog poddrveta sa korenom u čvoru v ako je vrednost v.minp re manja od vrednosti u.minp re ažuriramo vrednost u.minp re vector<vector<int>> listasuseda {{1, 2, {0, 3, 4, {0, 5, 8, {1, {1, 6, 7, {2,8, {4, {4, {5,2; int vreme = 1; vector<bool> posecen; vector<int> dolazna; vector<int> min_pretka; vector<int> roditelj; vector<pair<int,int>> most; 2

void dfs(int cvor){ posecen[cvor] = true; dolazna[cvor] = min_pretka[cvor] = vreme; vreme++; // rekurzivno prolazimo kroz sve susede koje nismo obisli for (auto sused : listasuseda[cvor]){ if (!posecen[sused]){ roditelj[sused] = cvor; dfs(sused); // nakon obrade podstabla sa korenom u susednom cvoru // azuriramo vrednost minpre za cvor ako je potrebno if (min_pretka[sused] < min_pretka[cvor]) min_pretka[cvor] = min_pretka[sused]; // proveravamo da li je ispunjen uslov da nijedan cvor u // poddrvetu sa korenom u cvoru sused // nije povezan sa nekim pretkom cvora cvor if (min_pretka[sused] > dolazna[cvor]) most.push_back(make_pair(cvor,sused)); // ukoliko grana vodi ka nekom pretku datog cvora // postavljamo vrednost minpre datog cvora na vrednost // dolazne numeracije suseda, ako je manja od tekuce vrednosti else if (sused!=roditelj[cvor]) if (dolazna[sused] < min_pretka[cvor]) min_pretka[cvor] = dolazna[sused]; void ispisi_mostove(int cvor){ int brojcvorova = listasuseda.size(); posecen.resize(brojcvorova, false); dolazna.resize(brojcvorova); min_pretka.resize(brojcvorova); roditelj.resize(brojcvorova, -1); dfs(cvor); cout << "Mostovi u grafu su: "; for (int i=0; i<most.size(); i++) cout << "(" << most[i].first << ", " << most[i].second << ") " ; cout << endl; 3

int main(){ ispisi_mostove(0); return 0; Pogledajmo na primeru jednostavnog neusmerenog grafa sa slike 3 kako bi išlo izvršavanje ovog algoritma. Slika 3: Primer grafa koji sadrži jedan most: (v 0, v 2 ) Pokrecemo DFS iz cvora v0, postavljamo v0.pre=1 i v0.minpre=1 Razmatramo suseda v1 čvora v0 Pokrecemo DFS iz cvora v1, postavljamo v1.pre=2 i v1.minpre=2 Razmatramo suseda v3 čvora v1 Pokrecemo DFS iz cvora v3, postavljamo v3.pre=3 i v3.minpre=3 Razmatramo suseda v0 čvora v3 Grana (v3,v0) je grana od potomka ka pretku pa postavljamo v3.minpre=v0.pre=1 Razmatramo suseda v1 čvora v3 To je grana ka roditelju, koju ne razmatramo Vracamo se u cvor v1 Posto vazi v3.minpre < v1.minpre postavljamo v1.minpre=v3.minpre=1 S obzirom da je v3.minpre < v1.pre grana (v1,v3) nije most Razmatramo suseda v0 čvora v1 To je grana ka roditelju, koju ne razmatramo Vracamo se u cvor v0 Posto vazi v1.minpre < v0.minpre postavljamo v0.minpre=v1.minpre=1 S obzirom da je v1.minpre = v0.pre grana (v0,v1) nije most Razmatramo suseda v3 čvora v0 v3.minpre=v0.minpre pa ne radimo nista 4

Pokrecemo DFS iz cvora v2, postavljamo v2.pre=4 i v2.minpre=4 Razmatramo suseda v0 čvora v2 To je grana ka roditelju, koju ne razmatramo Vracamo se u cvor v0 Posto vazi v2.minpre > v0.pre ne radimo nista S obzirom da je v2.minpre > v0.pre grana (v0,v2) jeste most Na sličan način možemo zaključiti da će čvor u biti artikulaciona tačka grafa ako je ispunjen jedan od naredna dva uslova: 1. u je koren DFS drveta i ima bar dva deteta 2. u nije koren DFS drveta i ima dete v u DFS drvetu takvo da nijedan čvor u poddrvetu sa korenom v nije povezan sa nekim pretkom čvora u u DFS drvetu Ako je zadovoljen prvi uslov, s obzirom na to da u neusmerenim grafovima ne postoje poprečne grane, izbacivanje korena DFS drveta dovelo bi do razbijanja grafa na veći broj komponenti (po jedna za svako dete korena DFS drveta). Drugi uslov označava situaciju kada nakon izbacivanja nekog čvora iz grafa više nije moguće doći iz proizvoljnog čvora poddrveta sa korenom u nekom od deteta tog čvora do proizvoljnog čvora iznad njega u DFS drvetu. Prvi od uslova se može detektovati tako što za svaki čvor proverimo da li ima roditelja prilikom DFS obilaska (jedino koren nema roditelja) i brojimo koliko ima dece. Drugi uslov je ekvivalentan uslovu kod određivanja mostova, tj. biće zadovoljen ako važi v.minp re u.p re. vector<vector<int>> listasuseda {{1, 2, {0, 3, 4, {0, 5, 8, {1, {1, 6, 7, {2,8, {4, {4, {5,2; int vreme = 1; vector<bool> posecen; vector<int> dolazna; vector<int> min_pretka; vector<int> roditelj; vector<bool> artikulacionatacka; void dfs(int cvor){ posecen[cvor] = true; dolazna[cvor] = min_pretka[cvor] = vreme; vreme++; int broj_dece = 0; // rekurzivno prolazimo kroz sve susede koje nismo obisli for (auto sused : listasuseda[cvor]){ if (!posecen[sused]){ broj_dece++; 5

roditelj[sused] = cvor; dfs(sused); if (min_pretka[sused] < min_pretka[cvor]) min_pretka[cvor] = min_pretka[sused]; // proveravamo da li je ispunjen prvi uslov: // cvor je koren DFS drveta i ima vise od jednog deteta if (roditelj[cvor] == -1 && broj_dece > 1) artikulacionatacka[cvor] = true; // proveravamo da li je ispunjen drugi uslov: // cvor nije koren DFS drveta i postoji dete tog cvora // takvo da nijedan cvor u njegovom poddrvetu // nije povezan sa nekim pretkom datog cvora if (roditelj[cvor]!= -1 && min_pretka[sused] >= dolazna[cvor]) artikulacionatacka[cvor] = true; else // posecen[sused] if (sused!= roditelj[cvor]) if (dolazna[sused] < min_pretka[cvor]) min_pretka[cvor] = dolazna[sused]; void ispisi_artikulacione_tacke(int cvor){ int brojcvorova = listasuseda.size(); posecen.resize(brojcvorova, false); dolazna.resize(brojcvorova); min_pretka.resize(brojcvorova); roditelj.resize(brojcvorova, -1); artikulacionatacka.resize(brojcvorova, false); dfs(cvor); cout << "Artikulacione tacke u grafu su: "; for (int i=0; i<artikulacionatacka.size(); i++){ if (artikulacionatacka[i]) cout << i << " "; cout << endl; int main(){ ispisi_artikulacione_tacke(0); return 0; 6

Topološko sortiranje Pretpostavimo da je zadat skup poslova u vezi sa čijim redosledom izvršavanja postoje neka ograničenja. Neki poslovi zavise od drugih, odnosno ne mogu se započeti pre nego što se ti drugi poslovi završe. Sve zavisnosti su poznate, a cilj je napraviti takav redosled izvršavanja poslova koji zadovoljava sva zadata ograničenja; drugim rečima, traži se takav raspored za koji važi da svaki posao započinje tek kad budu završeni svi poslovi od kojih on zavisi. Potrebno je konstruisati efikasni algoritam za formiranje takvog rasporeda. Ovaj problem se zove topološko sortiranje. Zadatim poslovima i njihovim međuzavisnostima može se na prirodan način pridružiti graf. Svakom poslu pridružuje se čvor, a usmerena grana od posla x do posla y postoji ako se posao y ne može započeti pre završetka posla x. Jasno je da graf mora biti aciklički (bez usmerenih ciklusa), jer se u protivnom neki poslovi nikada ne bi mogli započeti. Problem: U zadatom usmerenom acikličkom grafu G = (V, E) sa n čvorova numerisati čvorove brojevima od 1 do n, tako da ako je proizvoljan čvor v numerisan sa k, onda svi čvorovi do kojih postoji usmereni put iz v imaju broj veći od k. Slika 4: Aciklički usmereni graf u kojem postoji tačno jedno topološko uređenje čvorova B, A, D, C, E. Na primer, u grafu prikazanom na slici 4 postoji samo jedno ispravno topološko uređenje čvorova B, A, D, C, E. U opštem slučaju, može postojati veći broj ispravnih topoloških uređenja čvorova. Razmotrićemo dva različita algoritma za rešavanje ovog problema. Kanov algoritam Prirodna je sledeća induktivna hipoteza: umemo da numerišemo na zahtevani način čvorove svih usmerenih acikličkih grafova sa manje od n čvorova. 7

Bazni slučaj jednog čvora, odnosno posla, je trivijalan. Kao i obično, posmatrajmo proizvoljni graf sa n čvorova, uklonimo jedan čvor, primenimo induktivnu hipotezu i pokušajmo da proširimo numeraciju na polazni graf. Imamo slobodu izbora n-tog čvora. Trebalo bi ga izabrati tako da ostatak posla bude što jednostavniji. Potrebno je numerisati čvorove. Koji čvor je najlakše numerisati? To je očigledno čvor (posao) koji ne zavisi od drugih poslova, odnosno čvor sa ulaznim stepenom nula; njemu se može dodeliti broj 1. Da li se uvek može pronaći čvor sa ulaznim stepenom nula? Intuitivno se nameće potvrdan odgovor, jer se sa označavanjem negde mora započeti. Sledeća lema potvrđuje ovu činjenicu. Lema: Usmereni aciklički graf uvek ima čvor sa ulaznim stepenom nula. Dokaz: Ako bi svi čvorovi grafa imali pozitivne ulazne stepene, mogli bismo da krenemo iz nekog čvora unazad prolazeći grane u suprotnom smeru. Međutim, broj čvorova u grafu je konačan, pa se u tom obilasku mora u nekom trenutku naići na neki čvor po drugi put, što znači da u grafu postoji ciklus. Ovo je međutim suprotno pretpostavci da se radi o acikličkom grafu. Dakle u usmerenom acikličkom grafu uvek postoji čvor sa ulaznim stepenom nula. Slično bi se pokazalo da postoji i čvor sa izlaznim stepenom nula. Pretpostavimo da smo pronašli čvor sa ulaznim stepenom nula. Numerišimo ga sa 1, uklonimo sve grane koje vode iz njega, i numerišimo ostatak grafa (koji je takođe aciklički) brojevima od 2 do n (prema induktivnoj hipotezi oni se mogu numerisati od 1 do n 1, a zatim se svaki redni broj može povećati za jedan). Vidi se da je posle izbora čvora sa ulaznim stepenom nula, ostatak posla jednostavan. Jedini problem pri realizaciji ovog algoritma je kako pronaći čvor sa ulaznim stepenom nula i kako popraviti ulazne stepene čvorova posle uklanjanja grane. Možemo alocirati niz ulaznistepen dimenzije jednake broju čvorova u grafu i inicijalizovati ga na vrednosti ulaznih stepena čvorova. Ulazne stepene možemo jednostavno odrediti prolaskom kroz skup svih grana proizvoljnim redosledom (sve grane su navedene u listi povezanosti) i povećavanjem za jedan vrednosti ulaznistepen[w] svaki put kad se naiđe na granu (v, w). Čvorovi sa ulaznim stepenom nula stavljaju se u red (ili stek, što bi bilo jednako dobro). Prema prethodnoj lemi u grafu postoji bar jedan čvor v sa ulaznim stepenom nula. Čvor v se kao prvi u redu lako pronalazi; on se uklanja iz reda. Zatim se za svaku granu (v, w) koja izlazi iz v vrednost ulaznistepen[w] smanjuje za jedan. Ako brojač pri tome dobije vrednost nula, čvor w stavlja se u red. Posle uklanjanja čvora v graf ostaje aciklički, pa u njemu prema lemi?? ponovo postoji čvor sa ulaznim stepenom nula. Algoritam završava sa radom kad red koji sadrži čvorove stepena nula postane prazan, jer su u tom trenutku svi čvorovi numerisani. Interesantno je da ne moramo iz grafa izbacivati grane, već je samo važno da ažuriramo za svaki čvor njegov ulazni stepen. vector<vector<int>> listasuseda {{1, 2, {3, 4, {5, {, {6, 7, {8, {, {, {; 8

void topolosko_sortiranje(){ int brojcvorova = listasuseda.size(); // niz koji za svaki cvor cuva njegov ulazni stepen vector<int> ulaznistepen(brojcvorova,0); // niz koji za svaki cvor cuva njegov redni broj u topoloskom uredjenju vector<int> topoloskouredjenje; // broj posecenih cvorova int brojposecenih = 0; // inicijalizujemo niz ulaznih stepena cvorova for (int i=0; i<listasuseda.size(); i++) for (int j=0; j<listasuseda[i].size(); j++) ulaznistepen[listasuseda[i][j]]++; queue<int> cvorovistepenanula; // cvorove koji su ulaznog stepena 0 dodajemo u red for (int i=0; i<brojcvorova; i++) if (ulaznistepen[i] == 0) cvorovistepenanula.push(i); while(!cvorovistepenanula.empty()){ // cvor sa pocetka reda numerisemo narednim brojem int cvor = cvorovistepenanula.front(); cvorovistepenanula.pop(); topoloskouredjenje.push_back(cvor); brojposecenih++; // za sve susede tog cvora azuriramo ulazne stepene for(int i=0; i<listasuseda[cvor].size(); i++){ int sused = listasuseda[cvor][i]; ulaznistepen[sused]--; // ukoliko je stepen nekog od suseda pao na 0, dodajemo ga u red if (ulaznistepen[sused] == 0) cvorovistepenanula.push(sused); if (brojposecenih == brojcvorova){ cout << "Redosled cvorova u topoloskom uredjenju je:" << endl; for(int i=0; i<brojcvorova; i++) cout << topoloskouredjenje[i] << ": " << i+1 << endl; else 9

cout << "Graf nije aciklicki" << endl; int main(){ topolosko_sortiranje(); return 0; Složenost izračunavanja početnih vrednosti elementa niza ulaznistepen je O( V + E ). Za nalaženje čvora sa ulaznim stepenom nula potrebno je konstantno vreme (pristup redu). Svaka grana (v, w) razmatra se tačno jednom, u trenutku kad se v uklanja iz reda. Prema tome, broj promena vrednosti elemenata niza ulaznistepen jednak je broju grana u grafu. Vremenska složenost algoritma je dakle O( V + E ), odnosno linearna je funkcija od veličine ulaza. Algoritam zasnovan na DFS pretrazi Kao što smo ranije zaključili ako je (u, v) grana DFS drveta, direktna ili poprečna grana, za nju važi u.p ost > v.p ost, dok samo za povratne grane važi u.p ost v.p ost. Stoga ako za granu (u, v) važi u.p ost > v.p ost onda ona ne može biti povratna grana. U usmerenom acikličkom grafu ne postoji ciklus, te ne može postojati ni povratna grana u odnosu na DFS drvo. Stoga, ako uredimo čvorove grafa u opadajućem redosledu u odnosu na odlaznu numeraciju čvorova, dobićemo topološko uređenje grafa. Ovo važi zato što za proizvoljnu granu grafa (u, v), s obzirom na to da nije povratna, važi u.p ost > v.p ost, pa s obzirom na to da smo čvorove numerisali opadajuće prema odlaznoj numeraciji, čvor u biće numerisan manjom vrednošću od čvora v. vector<vector<int>> listasuseda {{1, 2, {3, 4, {5, {, {6, 7, {8, {, {, {; void dfs(int cvor, vector<bool> &posecen, vector<int> &odlazna){ posecen[cvor] = true; // rekurzivno prolazimo kroz sve susede koje nismo obisli for (auto sused : listasuseda[cvor]){ if (!posecen[sused]) dfs(sused,posecen,odlazna); // u vektor odlazna dodajemo na kraj naredni cvor // koji napustamo pri DFS obilasku odlazna.push_back(cvor); 10

void topolosko_sortiranje(){ int brojcvorova = listasuseda.size(); vector<bool> posecen(brojcvorova); // niz koji sadrzi redom cvorove prema redosledu napustanja vector<int> odlazna; for (int cvor=0; cvor<brojcvorova; cvor++) if (!posecen[cvor]) dfs(cvor,posecen,odlazna); cout << "Redosled cvorova u topoloskom uredjenju je:" << endl; for(int i = brojcvorova-1; i >= 0; i--) cout << odlazna[i] << ": " << brojcvorova-i << endl; int main(){ topolosko_sortiranje(); return 0; S obzirom na to da se ova implementacija svodi na DFS pretragu, vremenska složenost i ovog algoritma je O( E + V ). Komponente jake povezanosti grafa Za usmereni graf kažemo da je jako povezan ako je svaki čvor grafa dostižan iz svakog drugog čvora u grafu. Na skupu čvorova usmerenog grafa G = (V, E) može se definisati relacija obostrane dostižnosti: u v ako je čvor u dostižan iz čvora v i čvor v dostižan iz čvora u. Za ovu relaciju važi da je: refleksivna za svaki čvor u V je u u, simetrična za svaka dva čvora u, v V važi u v akko v u, tranzitivna za svaka tri čvora u, v, w V iz u v i v w sledi i u w. Stoga je ona relacija ekvivalencije. Ona razlaže skup čvorova V u klase ekvivalencije koje nazivamo komponente jake povezanosti grafa G (eng. strongly connected components). Na slici 5 prikazan je usmereni graf koji ima četiri komponente jake povezanosti koje se sastoje redom od čvorova {A, {B, C, {D, E, F, {G. Primetimo da svi čvorovi nekog ciklusa pripadaju istoj komponenti jake povezanosti. Graf G se može kompresovati i razmatrati kao usmereni aciklički graf koji se sastoji od svojih komponenti jake povezanosti (slika 5, desno): svaki čvor u ovom grafu odgovara jednoj komponenti jake 11

povezanosti, a dva čvora su povezana granom samo ako i samo ako u polaznom grafu postoji grana između nekog čvora jedne komponente i nekog čvora druge komponente. Jasno je da ovaj graf mora biti aciklički jer ako bi u njemu postojao ciklus to bi značilo da se sve komponente koje pripadaju ciklusu mogu spojiti u jednu veću komponentu povezanosti. Slika 5: Graf G i usmereni aciklički graf koji se sastoji od komponenti jake povezanosti grafa G. Direktan način da bi se odredile komponente jake povezanosti sastojao bi se u tome da se za prvi čvor v 0 odredi koji čvorovi pripadaju njegovoj jakoj komponenti povezanosti, tako što bi se za sve preostale čvorove proveravalo da li su obostrano dostižni iz v 0 to bi moglo da se uradi DFS pretragom iz čvora v 0 i iz svakog novog čvora čija se pripadnost komponenti ispituje. Nakon toga bi se sličan proces ponavljao za naredni čvor koji ne pripada jakoj komponenti kojoj pripada čvor v 0. Jasno je da bi ovo bilo veoma neefikasno. Postoji nekoliko različitih algoritama linearne vremenske složenosti za određivanje komponenti jake povezanosti u grafu, a najpoznatiji među njima su Tardžanov algoritam i Kosaradžuov algoritam. Oba algoritma su zasnovana na DFS obilasku grafa, samo se kod prvog sve radi u jednom prolazu, dok se u drugom dva puta poziva algoritam DFS pretrage. U nastavku ćemo razmotriti prvi od ova dva algoritma. Tardžanov algoritam Prilikom DFS obilaska datog usmerenog grafa G implicitno se formira DFS drvo, odnosno šuma. Bez narušavanja opštosti možemo pretpostaviti da je graf takav da postoji čvor iz kog se on može u potpunosti obići, odnosno da ima DFS drvo. Nazovimo baznim čvorom neke jake komponente onaj čvor te komponente koji ima najmanju vrednost dolazne numeracije. Lema: Neka je b bazni čvor jake komponente X. Tada za svako v X važi da je v potomak čvora b u odnosu na DFS drvo i svi čvorovi na putu od b do v pripadaju komponenti X. Dokaz: Dokažimo najpre prvo tvrđenje. Neka je v proizvoljni čvor iz X različit 12

od b. Važi da je (a) v potomak čvora b, (b) b potomak čvora v ili (c) nijedno od ova dva. Slučaj (b) nije moguć jer ako bi čvor b bio potomak čvora v onda bi on imao veću vrednost dolazne numeracije od v što je u suprotnosti sa pretpostavkom leme. Pretpostavimo da važi (c). Put od čvora b do čvora v mora da postoji jer ova dva čvora pripadaju istoj jakoj komponenti. Razmotrimo jedan takav put p i neka je r najbliži zajednički predak svih čvorova na tom putu. Čvor r mora pripadati tom putu p, a čvorovi b i v moraju biti potomci različite dece čvora r. Označimo sa T b poddrvo sa korenom u čvoru b, a sa T v poddrvo sa korenom u čvoru v. S obzirom na to da je vrednost dolazne numeracije čvora b manja od vrednosti čvora v i s obzirom na to da su T v i T b disjunktna drveta, ne može postojati grana ni od jednog čvora iz T b ka nekom čvoru iz T v. Stoga je jedini put od b do v kroz čvor r. Međutim, s obzirom na to da je r predak čvora b on ima manju vrednost dolazne numeracije od čvora b a pripada istoj jakoj komponenti jer postoji put od b do r, a i od r do b kroz grane drveta. Ovo je u suprotonosti sa pretpostavkom da je b bazni čvor te komponente, pa slučaj (c) nije moguć. Stoga važi da je čvor v potomak čvora b. Dokaz drugog dela leme je jednostavan. Neka je x čvor na putu od v do b. Postoji put od b do x kroz grane DFS drveta, a takođe i put od x do b tako što prvo idemo od x do v, pa od v do b. Stoga je x u istoj jakoj komponenti kao i čvor b. Lema: Neka je b bazni čvor i neka su b 1, b 2,... b k bazni čvorovi koji su potomci čvora b. Tada važi da je jaka komponenta kojoj pripada čvor b skup svih potomaka čvora b koji nisu potomci nijednog drugog čvora b 1, b 2,..., b k. Pretpostavimo suprotno, odnosno da postoji čvor v koji je u istoj jakoj komponenti kao i b i koji je potomak i čvora b i čvora b i za neko i, 1 i k. Mora da postoji put od v do b, a takođe i put od čvora b preko čvora b i do čvora v (koji se sastoji od grana DFS drveta). Odavde sledi da su b i b i u istoj jakoj komponenti što je u suprotnosti sa pretpostavkom. Lema: Čvor v je bazni čvor akko važi v.p re = v.minp re. Da bismo izdvojili čvorove koji pripadaju poddrvetu sa korenom u datom baznom čvoru, možemo iskoristiti stek na koji ćemo stavljati čvor prilikom prve posete tokom DFS obilaska grafa. Kada tokom obilaska naiđemo na čvor koji se već nalazi na steku, znamo da će jednoj komponenti povezanosti pripadati svi čvorovi koji se nalaze na steku počev od tog čvora. Poprečne grane neće biti razmatrane jer kada stignemo do čvora koji je već posećen, vršimo obradu samo ako se on nalazi na steku (što neće biti slučaj sa krajnjim čvorom poprečne grane). vector<vector<int>> listasuseda {{1, 2, {3, 4, {5, 8, {, {6, 7, {8, {1, {, {0; int vreme = 1; void dfs(int cvor, vector<int> &dolazna, vector<int> &min_pretka, 13

stack<int> &redosleduobilasku, vector<int> &u_steku){ dolazna[cvor] = min_pretka[cvor] = vreme; vreme++; redosleduobilasku.push(cvor); u_steku[cvor] = true; // rekurzivno prolazimo kroz sve susede koje nismo obisli for (auto sused : listasuseda[cvor]){ if (dolazna[sused] == -1){ dfs(sused,dolazna,min_pretka,redosleduobilasku,u_steku); if (min_pretka[sused] < min_pretka[cvor]) min_pretka[cvor] = min_pretka[sused]; // azuriramo vrednost minpre za cvor samo ako se sused nalazi u steku else if (u_steku[sused]) if (dolazna[sused] < min_pretka[cvor]) min_pretka[cvor] = dolazna[sused]; // ako je u pitanju koren komponente, stampamo sve cvorove te komponente if (dolazna[cvor] == min_pretka[cvor]){ while(1){ int cvor_komponente = redosleduobilasku.top(); cout << cvor_komponente << " "; u_steku[cvor_komponente] = false; redosleduobilasku.pop(); if (cvor_komponente == cvor){ cout << "\n"; break; void ispisi_komponente(int cvor){ int brojcvorova = listasuseda.size(); vector<int> dolazna(brojcvorova,-1); vector<int> min_pretka(brojcvorova); stack<int> redosleduobilasku; vector<int> u_steku(brojcvorova,false); cout << "Komponente jake povezanosti su: " << endl; dfs(cvor,dolazna,min_pretka,redosleduobilasku,u_steku); 14

int main(){ ispisi_komponente(0); return 0; Razmotrimo izvršavanje algoritma na primeru grafa prikazanog na slici 6. Slika 6: Primer grafa čije su komponente jake povezanosti {3, {8, {1, 4, 6, {0, 2, 5, 8. stek: 0 stek: 0,1 stek: 0,1,3 zavrsava se rekurzivni poziv iz cvora 3 i s obzirom na to da za cvor 3 vazi uslov v.pre=v.minpre=3 sa steka skidamo samo cvor 3 i on predstavlja zasebnu komponentu stek: 0,1 stek: 0,1,4 stek: 0,1,4,6 zavrsava se rekurzivni poziv iz cvora 6, ali za njega je v.pre=5, a v.minpre=2 pa on nije bazni cvor komponente zavrsava se rekurzivni poziv iz cvora 4, ali za njega je v.pre=4, a v.minpre=2 pa on nije bazni cvor komponente zavrsava se rekurzivni poziv iz cvora 1 i s obzirom na to da za cvor 1 vazi uslov v.pre=v.minpre=2 sa steka skidamo sve cvorove do cvora 1, dakle cvorove 6,4,1 i oni predstavljaju zasebnu komponentu 15

stek: 0 stek: 0,7 zavrsava se rekurzivni poziv iz cvora 7 i s obzirom na to da za cvor 7 vazi uslov v.pre=v.minpre=6 sa steka skidamo samo cvor 7 i on predstavlja zasebnu komponentu stek: 0 stek: 0,2 stek: 0,2,5 stek: 0,2,5,8 zavrsava se rekurzivni poziv iz cvora 8, ali za njega je v.pre=9, a v.minpre=1 pa on nije bazni cvor komponente zavrsava se rekurzivni poziv iz cvora 5, ali za njega je v.pre=8, a v.minpre=1 pa on nije bazni cvor komponente zavrsava se rekurzivni poziv iz cvora 2, ali za njega je v.pre=7, a v.minpre=1 pa on nije bazni cvor komponente zavrsava se rekurzivni poziv iz cvora 0 i s obzirom na to da za cvor 0 vazi uslov v.pre=v.minpre=1 sa steka skidamo sve cvorove do cvora 0, dakle cvorove 8,5,2,0 i oni predstavljaju zasebnu komponentu Ovaj algoritam je zasnovan na DFS obilasku grafa i složenosti je O( V + E ). 16