Noduri, muchii, arce ... (6) Introducere în teoria GRAFURILORÎn acest ultim episod vom aborda o serie de algoritmi legați de determinarea fluxului maxim într-o rețea de transport: vom prezenta o serie de proprietăți ale fluxurilor, metoda Ford-Fulkerson de determinare a fluxului maxim și a fluxului maxim de cost minim, implementarea Edmonds-Karp a acestei metode și o serie de cazuri particulare de flux, cum este problema cuplajului maxim într-un graf bipartit.
Definiție Printr-o rețea de transport înțelegem un graf orientat care conține două vârfuri speciale numite sursă și destinație și care are proprietatea că orice nod al său face parte dintr-un drum de la sursă la destinație. Sursa unei rețele de transport se notează cu s, iar destinația cu t.
Exemplul clasic de rețea de transport este reprezentat de o serie de conducte dispuse între un robinet s și un canal de scurgere t. Fiecare conductă (i, j) este caracterizată prin cantitatea maximă de apă c(i,j), care poate să treacă la un moment dat prin conductă. Problema aflării fluxului maxim presupune determinarea cantității maxime de apă care poate fi pompată prin robinetul s astfel încât pe nici o conductă să nu se depășească capacitatea maximă permisă. În figura 1 este prezentată o rețea de transport cu 7 noduri, dintre care o sursă s și o destinație t. Fiecărui arc îi este atașată o valoare pozitivă, reprezentând capacitatea maximă admisă pe arcul respectiv. Pentru a rezolva problema fluxului maxim folosim algoritmul Ford-Fulkerson. Pentru aceasta dublăm arcele grafului, introducând un arc de sens contrar între oricare două noduri între care deja există un arc. Vom numi aceste arce introduse de algoritm arce speciale. În fiecare moment suma celor două arce care unesc două noduri i, j ale grafului este egală cu capacitatea maximă dintre cele două vârfuri c(i,j). Vom nota cu a(i,j) ponderea arcului care există inițial în graf și cu a(j,i) ponderea arcului special. În fiecare moment al algoritmului, a(i,j) va reprezenta cantitatea de apă care mai poate fi pompată între nodurile i și j, iar a(j,i) va reprezenta valoarea fluxului dintre i și j. Deci în orice moment avem a(i,j) + a(j,i) = c(i,j). Iată, de exemplu, rezolvarea problemei fluxului maxim pentru graful din figura 1:
Avem de-a face deci cu un flux de valoare 10, fluxul pe fiecare arc fiind: pe arcul (s-4) un flux de valoare 8, pe arcul (s-1) un flux de valoare 2, pe arcul (1-3) un flux de valoare 0, pe arcul (5-t) un flux de valoare 5 etc. De fapt, problema fluxului maxim cere găsirea unei funcții f:UźR, (U este mulțimea arcelor), f(i,j) reprezentând valoarea fluxului pe arcul (i,j). Funcția f trebuie să satisfacă următoarele proprietăți: 1) f(i,j) Ł c(i,j) pentru oricare două noduri i, j; 2) pentru orice nod k ± s, t;
3) , unde F este valoarea fluxului maxim.
Definiție: Prin drum de creștere într-o rețea de transport înțelegem un drum de la s la t care conține arce de cost pozitiv, care pornesc atât din cele inițiale, cât și din cele speciale. În figura 1, în care toate arcele speciale au ponderea 0, un posibil drum de creștere este drumul s-1-3-5-2-t. În figura 2, nu mai există nici un drum de creștere. Valoarea unui drum de creștere este egală cu valoarea arcului de cost minim de pe drumul respectiv, numit arc critic. De exemplu, pentru drumul s-1-3-5-2-t din figura 1, valoarea acestuia este min(2, 2, 8, 3, 6) = 2 și avem două arce critice: (s-1) și (1-3).
Algoritmul Ford-Fulkerson are următorii pași:
Ford_Fulkerson(rețea transport G) FŹ0 cât timp mai există drumuri de creștere determină un drum de creștere D vŹvaloarea lui D FŹF+v pentru fiecare (i,j)ÎD a(i,j)Źa(i,j)-v a(j,i)Źa(j,i)+v
În cele ce urmează vom încerca să lămurim cititorul de corectitudinea acestui algoritm: să presupunem că pentru graful din figura 1 găsim la început drumul s-1-3-5-t, la pasul 2 drumul s-4-3-5-t și la pasul 3 drumul s-4-3-5-2-t. Va rezulta graful din figura 3:
Aceste prime trei drumuri sunt compuse doar din arce care existau inițial în graf. În acest moment avem un flux de valoare 8 și nu mai există drumuri de creștere formate doar din arce inițiale. Să vedem ce semnificație au drumurile care conțin și arce speciale. În cazul de față singurul drum de creștere care mai există în graf este drumul de valoare 2: s-4-3-1-2-t care conține arcul special (3-1). Semnificația parcurgerii acestui arc este că "scoatem" apa de pe conducta respectivă. Studiind acum ce se întâmplă cu trecerea apei prin conducte, se remarcă următoarele: - pe conducta (1-3) am scos toată apa, deci pe aici nu mai trece nici o cantitate de apă; - în nodul 1 am redirecționat fluxul de valoare 2 (care ajungea prin conducta (s-1) ) prin conducta (1-2); - fluxul care ajunge în nodul 3 va fi în continuare de valoare 8, numai că acum va ajunge în întregime de pe conducta (4-3), deoarece pe conducta (1-3) s-a scos toată apa. Să analizăm complexitatea algoritmului Ford-Fulkerson: găsirea unui drum de creștere se face în O(n+m), la fiecare iterație valoarea fluxului este mărită cu cel puțin o unitate, deci numărul maxim de iterații este F. În concluzie, complexitatea algoritmului Ford-Fulkerson este O(F(n+m)). Pentru valori mari ale fluxului, această dependență de valoarea fluxului poate deranja. Să considerăm graful din figura 4. În cazul în care algoritmul va găsi drumurile de creștere s-1-t și s-2-t, algoritmul se va termina în două iterații. În cazul în care algoritmul va găsi alternativ drumurile s-1-2-t și s-2-1-t, acesta se va termina după 2000000 de iterații! Pentru a evita astfel de situații vom prezenta succint ideea algoritmului Edmonds-Karp, care este de fapt o implementare eficientă a algoritmului Ford-Fulkerson. Acest algoritm, în loc să găsească un drum de creștere la întâmplare, va găsi la fiecare pas un drum de creștere cu număr minim de arce. Acest lucru se realizează foarte ușor, printr-o simplă parcurgere în lățime. Astfel, se garantează că numărul maxim de iterații pe care le realizează algoritmul este n·m. Demonstrația acestui fapt este destul de simplă: fiecare drum de creștere conține, așa cum rezultă din definiție, cel puțin un arc critic. Să presupunem că arcul (i,j) apare pentru prima oară ca arc critic într-un drum de creștere în momentul în care acesta se află la distanța d de sursă. Se arată ușor că, alegând de fiecare dată un drum de creștere cu număr minim de muchii, în momentul în care arcul (i,j) va apare pentru a doua oară ca arc critic, el se va afla la o distanță de cel puțin d+2 de sursă. În concluzie fiecare arc (i-j) va putea fi critic de cel mult [n/2] ori, deci vom avea cel mult O(n) drumuri de creștere caracterizate prin arcul critic (i-j). În total vor exista cel mult O(n·m) drumuri de creștere, deci complexitatea totală a implementării algoritmului Edmonds-Karp va fi O((n+m)·n·m)=O(n·m)2. Un alt fapt interesant este găsirea tăieturii de capacitate minimă.
Definiție: Fie G(V,U) o rețea de transport și SÌV o mulțime de noduri astfel încât sÎS și tÏS. Mulțimea arcelor (i,j) cu i în S și j în V\S se numește tăietură în rețeaua de transport G. Capacitatea unei tăieturi este dată de suma capacităților arcelor care o compun. Tăietura se notează cu S, iar capacitatea acesteia cu c(S). Folosindu-ne de exemplul dat anterior, problema găsirea tăieturii de capacitate minimă presupune găsirea acelor conducte pentru care suma capacităților este minimă și prin "astuparea" cărora apa nu mai poate ajunge de la sursă la destinație. În cele ce urmează vom prezenta teorema de flux maxim - capacitate minimă care demonstrează corectitudinea algoritmului Ford-Fulkerson și care sugerează algoritmul de găsire a tăieturii de capacitate minimă.
Teoremă: Fie o rețea de transport G(V,U) și F valoarea fluxului maxim din rețea. Atunci următoarele afirmații sunt echivalente: 1) F este flux maxim în rețea 2) Rețeaua de transport nu conține nici un drum de creștere 3) Există o tăietură S pentru care F=c(S) 1) Ț 2) Această implicație este evidentă. Să presupunem prin absurd că în rețeaua de transport am mai găsi un drum de creștere de valoare v. Atunci, conform algoritmului Ford-Fulkerson, am putea mări valoarea fluxului maxim cu v. Contradicție cu faptul că F este fluxul maxim în rețeaua de transport G. 2) Ț 3) Dacă rețeaua de transport nu conține drumuri de creștere, atunci vom considera mulțimea S ca fiind mulțimea tuturor vârfurilor la care se mai poate ajunge din s. Evident t nu aparține lui S - deoarece în G nu mai există drumuri de creștere - deci S este o tăietură validă. Remarcăm că pentru fiecare arc (i,j) din S (i Î S și j Î V\S) f(i,j) = c(i,j) deoarece altfel am fi putut ajunge și în nodul j, deci j ar fi făcut parte din S (contradicție). Dar: , deci c(S)=F.
3) Ț 1) Este evident că pentru o tăietură oarecare X din G, fluxul maxim F Ł c(X). Atunci, din egalitatea F=c(S) rezultă că F este fluxul maxim din rețeaua de transport G.
Teorema indică și algoritmul de determinare a tăieturii de capacitate minimă într-o rețea de transport: se aplică algoritmul Ford-Fulkerson și se rețin nodurile la care putem ajunge din s în momentul în care nu mai avem drumuri de creștere. Aceste noduri vor forma mulțimea S care caracterizează tăietura de capacitate minimă. Așa cum am demonstrat în teorema de mai sus, valoarea tăieturii de capacitate minimă este egală cu valoarea fluxului maxim. În momentul în care într-o rețea de transport avem asociat pentru fiecare arc, pe lângă capacitate, și un cost unitar, atunci se pune problema aflării unui flux maxim de cost minim. Această problemă se poate rezolva tot cu ajutorul algoritmului Ford-Fulkerson, cu condiția ca la fiecare pas să se determine un drum de creștere de cost minim. Aflarea unui astfel de drum este posibilă folosind algoritmul Bellman-Ford. Algoritmul Dijkstra nu se poate aplica în acest caz, deoarece - așa cum am arătat într-un articol precedent - acest algoritm nu funcționează în cazul existenței muchiilor negative, iar în acest caz costul arcelor introduse de algoritm va putea fi negativ. Alte situații speciale care pot apărea sunt: · rețea de transport cu mai multe surse și mai multe destinații: în acest caz introducem o supersursă ss și o superdestinație st. Ducem de la ss la toate sursele arce de capacitate și de asemenea, de la toate destinațiile la st arce de capacitate. În acest fel am redus problema la determinarea fluxului într-o rețea de transport cu o singură sursă ss și o singură destinație st; · rețea de transport cu capacități și în noduri, adică într-un nod poate intra o cantitate de apă cel mult egală cu capacitatea nodului respectiv. În acest caz, desfacem fiecare nod n în două noduri n1 și n2, între care punem un arc de capacitate egală cu capacitatea nodului n. Toate arcele care intrau în nodul inițial n vor intra acum în nodul n1, iar toate arcele care ieșeau din nodul inițial n vor ieși acum din nodul n2. Astfel, am redus problema la determinarea fluxului maxim într-o rețea de transport cu capacități doar pe arce; · problema cuplajului maxim într-un graf bipartit este un caz particular de flux maxim într-o rețea de transport. Să presupunem că avem o listă de n elevi și n licee și o listă de preferințe de forma (e, l) având semnificația că elevul e dorește să studieze la liceul l. Fiecare elev poate să dorească în egală măsură să studieze la mai multe licee. Problema cere ca - dacă este posibil - să se atașeze fiecărui elev un liceu unic, astfel încât fiecare elev să fie repartizat într-un liceu în care dorește să studieze. Problema se modelează printr-un graf bipartit, având pe de o parte mulțimea elevilor, iar pe de cealaltă parte mulțimea liceelor. Între un elev și un liceu există arc doar dacă elevul dorește să studieze la liceul respectiv. Problema cere selectarea unui număr maxim de arce ale grafului bipartit, astfel încât fiecărui elev să-i fie asociat un liceu unic și invers. În cazul în care numărul maxim de perechi valide este n, problema are soluție. Pentru rezolvare, introducem o sursă virtuală s și o destinație virtuală t. Ducem arc între nodul sursă și fiecare elev, și între fiecare liceu și nodul destinație. Toate arcele din problemă vor avea capacitatea 1. Astfel, ne asigurăm că fiecărui elev îi este asociat un singur liceu și invers. Am redus și de această dată problema la determinarea unui flux maxim într-o rețea de transport. Bibliografie 1. Cormen T., Leiserson C., Rivest R., Introducere în algoritmi, Editura Computer Libris Agora, 2000 2. Georgescu H., Livovschi L., Analiza și sinteza algoritmilor, Editura Științifică și Enciclopedică, 1986 3. Mateescu E., Maxim I., Arbori, Editura Țara Fagilor, 1996 4. Cadar C., Stroe M., Culegere de probleme și programe PASCAL, Editura Petrion, 1999 Cristian Cadar [cuprins] |