Sunteți pe pagina 1din 6

Algoritmul lui Kuhn

Tiberiu-Lucian Florea November 21, 2005

Introducere

Voi prezenta continuare problema afectrii n a mpreun cu una din cele mai a eciente solutii pentru rezolvarea ei: Algoritmul lui Kuhn. ultima parte a In articolului, voi oferi un exemplu de implementare uor de folosit concursurile s n de informatic. Se presupun cunoscute notiunile de cuplaj maxim i suport a s minim ntr-un graf bipartit, precum i modul de obtinere a unui cuplaj maxim s ntr-un graf bipartit cu ajutorul drumurilor de cretere. S s a ncepem cu denitia problemei discutate. Problema de afectare Exista m muncitori i n lucrri, ecare muncitor putnd s a a efectua una sau mai multe lucrri. Notm muncitorii cu x1 , x2 , . . . , xm , a a lucrrile cu y1 , y2 , . . . , yn , i asociem costul vij 0 efecturii de ctre a s a a muncitorul xi a lucrrii yj , faptul c vij = avnd semnicatia c muncia a a a torul xi nu poate efectua lucrarea yj . S se gseasc o repartizare a celor a a a m muncitori la cele n lucrri astfel at un muncitor s efectueze cel mult a nc a o lucrare, iar o lucrare s e efectuat de cel mult un muncitor, cu conditia a a ca costul total de executie s e minim. a Denim matricea de afectare astfel: X = (xij ), i = 1, m, j = 1, n, xij = 1 dac muncitorul xi efectueaz lucrarea yj , si xij = 0 caz contrar. Cnd a a n a = min(m, n), matricea de afectare se numete saturant. Voi prezenta s a i,j algoritmul elaborat in 1955 de Kuhn, numit de acesta algoritmul ungar pentru rezolvarea problemelor de afectare denite de matrice saturante, cunoscut i sub numele de metoda ungar, deoarece se bazeaz pe rezultatele a doi s a a matematicieni maghiari: D. Knig si E. Egervry. Demonstratia va presupune o a c m = n; se va vedea apoi c algoritmul se poate extinde foarte uor la matrice a a s care nu sunt ptrate. a

Descrierea algoritmului

Algoritmul utilizeaz urmtoarea proprietate: a a Propozitia 1 Multimea solutiilor minime ale unei probleme de afectare nu se modic dac la toate elementele unei linii sau coloane a matricei costurilor se a a adun acelai numr real . a s a 1

De asemenea, este necesar cunoasterea urmtoarei teoreme: a a Teorema 1 (Teorema lui Knig) Fie G un graf bipartit, (G) cardinalul o unui cuplaj maxim n acest graf, si (G) cardinalul unui suport minim. Atunci exist egalitatea: a (G) = (G), (1) adic numrul maxim de muchii ale unui cuplaj este egal cu numrul minim de a a a vrfuri ale unui suport. a Deoarece m = n i matricea de afectare este saturant, orice solutie a probs a lemei de afectare contine un singur 1 ecare linie i ecare coloan, deci, n s n a prin transformarea matricei costurilor, costul asociat oricrei solutii creste cu a . Din acest motiv, multimea solutiilor minime ale problemei de afectare nu se modic prin transformri de acest tip ale matricei costurilor. a a Algoritmul lui Kuhn se bazeaz i pe faptul c o solutie a problemei de afectare as a corespunde unui cuplaj al grafului bipartit cu prtile X = {x1 , x2 , . . . , xn } i a s Y = {y1 , y2 , . . . , yn }, i se desfoar mai multi pai, ind prezentat aici s as a n s ntr-o variant modicat i simplicat fat de cea original. Ideea este urmtoarea: a as a a a a dac prin anumite operatii de adunare a unei constante la toate elementele unei a linii sau coloane a matricei costurilor toate numerele din matrice ramn pozitive a i exist un cuplaj de cardinal n graful bipartit denit de zerourile matricei, s a n atunci solutia problemei se gasete pe pozitiile nule din matrice. s Acest lucru se demonstreaz imediat pe baza propozitiei 1, avnd vedere a a n faptul c matricea care contine numai numere nenegative nu poate exista o a n transversal cu costul negativ. Vom a ncerca, deci, s aplicm mod repetat a a n transformrile descrise, pn cnd va exista un cuplaj de cardinal maxim. a a a a Vom adopta urmtoarele conventii de transpunere a limbajului de teoria grafua rilor termeni de matrice: n Spunem despre o linie sau despre o coloan c este acoperit dac la un a a a a anumit pas face parte din multimea nodurilor marcate cadrul procesului n de determinare a unui suport minim. Spunem despre un element al matricei c este a ncercuit dac face parte a din cuplajul gsit pn momentul respectiv. a a a n Spunem despre un element al matricei c este tiat dac corespunde unei a a a muchii care va putea folosit pentru obtinerea unui drum de cretere, a s ntr-un sens ce va claricat ulterior.

Algoritmul propriu-zis

Initial, toate liniile si coloanele sunt decuplate. Algoritmul se va desfura as n n pai, ecare pas decurgnd dup cum urmeaz: Se descoper toate liniile i s a a a a s coloanele matricei i se acoper toate coloanele cuplate. Se pstreaz elementele s a a a ncercuite, dar se consider c nici un element nu este tiat. Pornind de la a a a

cuplajul obtinut la pasul anterior, se determin un suport minim de acelai car a s dinal, adic o multime de linii i coloane care acoper toate zerourile. Modul a s a de obtinere a suportului minim a fost dezvoltat de Egervry, iar demonstratia a corectitudinii sale depete scopul acestui articol. Cititorii interesati pot conas s sulta [1] pentru o demonstratie complet. Atta timp ct putem gsi un zero a a a a descoperit pe o linie i i o coloana j, tiem i considerm urmtoarele doua s l a s a a cazuri: Linia i este cuplat Acoperim linia i i descoperim coloana cu care este cua s plat. Coloana cu care este cuplat linia i va mereu acoperit din cauza a a a modului care lucreaz algoritmul: orice moment ori linia ori coloana n a n pe care se a un zero a ncercuit vor acoperite, deoarece initial toate coloanele cuplate sunt acoperite, i singura operatie pe care o efectum s a este descoperirea unei coloane si acoperirea liniei cu care aceasta este cuplat. a Linia i nu este cuplat a Incercm s construim un drum de cretere, dup a a s a cum urmeaz: Pornim de pe pozitia pe care tocmai am tiat-o. Dac a a a coloana care se a nu este cuplat, cuplm linia i cu coloana j, i n a a a s drumul de cretere este complet. Dac coloana j este cuplat, continum s a a a drumul de cretere cu zeroul s ncercuit din coloana j i zeroul tiat care s a se gsete pe linia acelui zero. Fie k linia cu care este cuplat coloana j. a s a (k, j) este ncercuit, coloana j nu este acoperit, ceea ce a nseamn c linia a a k este acoperit. Dar o linie nu poate acoperit dect conditiile care a a a n n la un pas anterior am gsit un zero descoperit acea linie, l-am tiat, a n a si am descoperit coloana din care fcea parte. concluzie, vom putea a In gsi mereu un zero tiat pe linia care ne intereseaz. Deoarece numrul a a a a elementelor ncercuite este nit, ecare din ele va selectat cel mult o dat, i vom putea mereu s gsim un zero tiat cu care s continum a s a a a a a drumul de cretere, rezult c cele din urm ori vom gsi un zero tiat s a a n a a a ntr-o coloan necuplat, moment care drumul de cretere va complet. a a n s Dac la pasul anterior nu am gsit un drum valid de cretere, vom cona a s sidera matricea format din elementele care nu apartin unor linii sau coloane a acoperite i vom calcula minimul al elementelor acestei submatrice. Obtinem s > 0, deoarece elementele nule ale matricei se gsesc numai in liniile i coloanele a s acoperite. Vom scdea din elementele coloanelor neacoperite i vom aduna a s l la elementele liniilor acoperite. Deoarece toate zerourile sunt acoperite o singur a dat conform modului de obtinere a suportului minim, aceste operatii nu vor a face s dispar din zerourile obtinute pn la acest pas, i nici nu vor provoca a a a a s aparitia unor elemente negative, a vor produce cel putin a un zero, pe ns nc pozitia pe care a fost gsit minimul. Suportul minim al matricei costurilor a va crete cu cel putin o unitate prin aplicarea repetat a acestor pai. Cons a s form teoremei lui Knig, aceasta o nseamn c numrul elementelor unui cuplaj a a a maxim al matricei obtinute crete cu cel putin o unitate, deci cele din urm s n a vom reui s gsim un drum de cretere cu ajutorul cruia s mrim cuplajul s a a s a a a obtinut. Concluzia pe care o tragem este urmtoarea: la ecare din cei n pai a s 3

vom repeta aplicarea operatiilor descrise pn la obtinerea unui drum de ame a a liorare, iar cuplajul maxim va crete cu 1. Dup cei n pai, vom avea un cuplaj s a s de cardinal n care va corespunde transversalei minime din matricea costurilor. Complexitatea algoritmului descris este O(N 4 ), a se comport bine pracns a n tic, functie de costurile muchiilor grafului pe care se realizeaz cuplajul. a n a

Detalii de implementare

Algoritmul lui Kuhn este destul de cunoscut de ctre participantii la concursurile a de informatic, dar nu este folosit foarte des, deoarece se consider c este mult a a a prea greu de implementat. continuare se va vedea c, cu putin atentie, In a a metoda descris mai sus este implementabil timp de concurs, cel mult 10 a a n n minute. Avem nevoie de o matrice G care va retine graful propriu-zis. Pentru a nu irosi spatiul, loc de a memora alt parte matricea modicat, vom memora n n a a in vectorii vr si vc suma valorilor care au fost adugate pe o anumit linie, a a respectiv sczute pe o anumit coloan. Vectorii l i r vor retine cu cine este a a a s cuplat o anumit linie, respectiv coloan, sau 0 dac acea linie / coloan nu a a a a a a fost cuplat a. pi = j are semnicatia c (i, j) este tiat, iar vectorii cr i cc a nc a a s sunt folositi pentru a aa rapid dac o linie / coloan este acoperit. Fr alte a a a a a comentarii, voi trece direct la prezentarea codului surs care implementeaz pas a a cu pas cele descrise de mai sus. #include <stdio.h> #include <string.h> int N, G[256][256], l[256], r[256], p[256], cr[256], cc[256], vr[256], vc[256]; void find_zero () { int i, j, min, t; for (min = 1<<30, i = 1; i <= N; ++ i) if (!cr[i]) for (j = 1; j <= N; ++ j) if (!cc[j]) min <?= G[i][j] + vr[i] - vc[j]; for (i = 1; i <= N; ++ i) if ( cr[i]) vr[i] += min; for (j = 1; j <= N; ++ j) if (!cc[j]) vc[j] += min; for (i = 1; i <= N; ++ i) if (!cr[i]) for (j = 1; j <= N; ++ j) if (!cc[j] && G[i][j] + vr[i] == vc[j]) if (r[i]) { p[i] = j, cr[i] = 1, cc[ r[i] ] = 0; break; } else { do t = l[j], r[i] = j, l[j] = i, i = t, j = p[i]; while (t); return; }

find_zero (); } int main () { int i, j, min, cnt; scanf ("%d", &N); for (i = 1; i <= N; ++ i) for (j = 1; j <= N; ++ j) scanf ("%d", &G[i][j]); memset (vr, 0, sizeof (vr)), memset (vc, 0, sizeof (vc)); memset (l, 0, sizeof (l)), memset (r, 0, sizeof (r)); for (cnt = 0; cnt < N; ++ cnt) { memset (cr, 0, sizeof (cr)), memset (p, 0, sizeof (p)); memcpy (cc, l, sizeof (cc)); find_zero (); } return 0; }

Optimizri a

Codul de mai sus a fost destul de compactat si optimizat at s nu mai nc a aib nevoie dect de urmtorul pas pentru a stoarce i ultima pictur de a a a s a a performant din el: Nu este nevoie s pornim cu cuplajul de cardinal 0. La a a nceput scdem valoarea minim din ecare linie, apoi scdem valoarea minim a a a a din ecare coloan. acest moment putem s parcurgem matricea pas cu a In a pas i, cnd gsim un element nul a crui linie i coloan nu au fost cuplate s a a a s a l adugm la cuplajul initial. Astfel, nu vom mai nevoiti s facem n pai, iar a a a s timpul de executie va scdea simtitor. a

Extinderi

Dup cum am promis, algoritmul lui Kuhn va putea aplicat i pe matrice a s ne-ptrate. Dac m = n vom transforma matricea costurilor astfel: a a 1. pentru m < n, se adaug matricei costurilor initiale n m linii care contin a numai 0. 2. pentru m > n, se adaug matricei costurilor initiale m n coloane care a contin numai 0. cazul unor probleme de afectare pentru care se caut o afectare saturant In a a care maximizeaz suma a xij vij , vom deni o nou matrice a costurilor, a i,j ale crei elemente sunt: vij = v0 vij , i = 1, m, j = 1, n, v0 = maxi,j vij . a Observm c dac matricea costurilor initial contine un element egal cu a a a a aceast problem este banal, deci presupunem v0 < . Solutia de cost minim a a a a problemei cu matricea costurilor modicat va coincide cu solutia de cost a 5

maxim a problemei de afectare cu matricea costurilor initial. Demonstratia a este imediat, i rmne c tem cititorului. a s a a a a

References
[1] Caius Iacob, Matematici clasice i moderne, vol. I, Bucureti: Editura s s Tehnic, 1978 a

S-ar putea să vă placă și