Sunteți pe pagina 1din 21

Algoritmul ungar prof.

Maria şi Adrian NIŢĂ

ALGORITMUL UNGAR

Suport teoretic

Matematica oferă modele ce se pot aplica în cele mai diverse probleme ale naturii. Se pot studia
probleme legate de teoria grafurilor , teoria jocurilor, teoria stocurilor, probleme de repartiţie.

Problemele de repartiţie, cu largă aplicabilitate practică, sunt probleme în care se urmăreşte


asocierea optimă a elementelor unei mulţimi X = {x1, x2, ... , xp} cu elementele unei alte mulţimi Y
= {y1, y2, ... , yq} în anumite condiţii impuse.

În general, fiecare asociere posibilă xi  yj aduce un anumit efect cij (profit, cost etc) care poate fi
calculat,vom presupune că este cunoscut şi îl vom reprezenta printr-o matrice C=( cij)p,q.

Condiţiile asupra asocierilor se traduc de obicei prin faptul că:

 Un element xi poate fi asociat doar cu anumite elemente din Y şi reciproc;


 La sfârşit, fiecărui element din X i s-a asociat cel mult un element din Y şi reciproc.

Asocierea optimă presupune, de obicei, două obiective:

 Să se facă maximul de asocieri, realizndu-se cuplajul maxim;


 Suma efectelor asocierilor să fie maximă (sau minimă, în funcţie de semnificaţia acestora).

Cele două mulţimi X şi Y reprezintă partiţionarea mulţimii nodurilor unui graf şi realizarea unui
graf bipartit complet.
Reprezentarea geometrică a situaţiei de mai sus este un graf de forma:

x1
y1

x2
y2

yq
xp

numit graf bipartit.

Definiţie: Se numeşte graf bipartit un graf G = (X, U) în care mulţimea nodurilor, X poate fi
partiţionată în două mulţimi disjuncte A şi B astfel încât orice arc are extremitatea iniţială în A şi
cea finală în B şi orice nod din mulţimea A este adiacent cu orice nod din mulţimea B.

Definiţie: Se numeşte cuplaj al unui graf bipartit o submulţime de arce W  U cu proprietatea că


nu există două arce adiacente (sau altfel spus, pentru orice nod există cel mult un arc incident
acestuia).
1
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Definiţie: Se numeşte cuplaj maxim un cuplaj cu proprietatea că orice arc care nu face parte din
cuplaj este adiacent cu un arc din cuplaj (posedă un număr maxim de arce.

Concluzie: Afirmaţiile de mai jos sunt echivalente:


 orice arc am adăuga, nu mai rămâne cuplaj;
 nu există nici un cuplaj în care să se includă strict;
 conţine numărul maxim de arce neadiacente.

În 1931 apare:

Teorema lui König (numărul de arce ale unui cuplaj maxim): Numărul maxim de arce ale unui
cuplaj într-un graf bipartit G = (AB, ) este egal cu min A  C   C  
C A

Este interesant de văzut însă cât de mare este el efectiv şi în ce condiţii este egal chiar cu min
(A,B).

Observaţie: Putem presupune că întotdeauna AB, în caz contrar inversăm sensul tuturor
arcelor grafului, problema rămânând aceeaşi. În acest caz:

min A  C   C   = A  min A  C   C   – A = 0  min   C   C   = 0 


C A C A C A

 max
C A
 C   C   = 0   C   C oricare ar fi C  A
sau altfel spus, pentru orice submulţime C a lui A, mulţimea nodurilor atinse de arcele care pleacă
din nodurile sale, adică (C), are cel puţin atâtea elemente cât C.

Presupunem, în continuare, că s-a asociat fiecărui arc (xi, yj) o valoare cij.

Definiţie: Se numeşte valoare a unui cuplaj suma valorilor arcelor care îl formează.

În acest moment putem spune că determinarea unei asocieri optime a mulţimilor X şi Y de la


început este echivalentă matematic cu determinarea unui cuplaj maxim de valoare optimă (minimă
sau maximă) în graful bipartit asociat.

Dintre problemele întâlnite în practica economică, ce se reduc matematic la găsirea unui cuplaj
maxim de valoare optimă, amintim:

1. Problema repartizării muncitorilor unei secţii la utilajele acesteia în funcţie de pregătirea şi


preferinţele muncitorilor, complexitatea maşinilor etc;
2. Transferarea unor informaţii într-un grup;
3. Repartizarea angajaţilor pe posturi;
4. Formarea grupelor de lucru după afinităţile dintre membrii colectivului.

Pe baza Teoremei lui König, în anul 1955, H.W. Kuhn elaborează un algoritm, cunoscut în
literatura de specialitate sub denumirea de algoritmul ungar. Cu ajutorul acestui algoritm se poate
determina un cuplaj maxim de valoare minimă într-un graf bipartit complet pentru care |A| = |B| =n

2
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

El se bazează pe observaţia că, dacă se adună (sau scade) aceeaşi număr la toate valorile
arcelor, nu se modifică ierarhia cuplajelor maxime, în ceea ce priveşte valoarea lor.

Fie matricea C = (cij)p,q, unde cij ≥ 0, reprezintă valoarea cuplajului (xi, yj).

Algoritmul ungar - descriere:

Etapa I. Obţinerea de zerouri:

Pentru fiecare coloană se va scădea elementul cel mai mic al ei (minimul) din toate celelalte
elemente ale ei; în matricea obţinută se va proceda la fel pentru linii: se va scădea elementul cel mai
mic (minimul) din toate celelalte elemente ale ei.

Etapa II. Căutarea unei soluţii optime:

Cu zerourile obţinute la prima etapă, se caută o soluţie de valoare zero (adică o repartiţie în care toţi
(cij) corespunzători să fie zero) astfel:
 se alege linia cu cele mai puţine zerouri şi se încadrează unul din zerouri;
 se barează zerourile care se găsesc pe aceeaşi linie sau coloană cu zeroul încadrat.
 se procedează la fel pe toate liniile.
Dacă nu s-a obţinut o soluţie de valoare zero (au fost alese toate valorile pentru cuplaj) se trece la
etapa III.

Etapa III. Determinarea unui cuplaj maxim astfel:

a) se marchează toate liniile care nu conţin nici un zero încadrat.


b) se va marca fiecare coloană care are unul sau mai multe zerouri barate în una din
liniile marcate la punctul a).
c) se va marca fiecare linie care are un zero încadrat într-o coloană marcată.
d) se repetă operaţiile b) şi c) până când nu mai este posibil să se obţină alte linii sau coloane
marcate.

Etapa IV. Obţinerea unui suport minim:

Se elimină (logic, nu vor fi luate în calcule) liniile nemarcate şi coloanele marcate la etapa III.

Etapa V. Deplasarea eventuală a unor zerouri.

În tabloul parţial obţinut se alege minimul. Se scade această valoare din coloanele care nu sunt
eliminate şi se adună liniilor care sunt eliminate la etapa anterioară. Cu tabloul nou obţinut se repetă
procedeul începând tot cu etapa I, până când etapa a II va da o soluţie optimă.

Soluţia optimă poate să nu fie unică.

Dacă se caută repartiţie maximală se aplică algoritmul ungar pentru matricea

D =(dij)p,q, unde dij = max(cij) - cij

3
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Exemple:
1. Şase localităţi (x) sunt aprovizionate de şase depozite (y).Costurile sunt date de tabloul de mai
jos. Ştiind că aprovizionarea fiecărei localităţi se face de către un singur depozit, să se determine
repartiţia depozitelor pe localităţi, astfel încât costul să fie minim.

y1 y2 y3 Y4 y5 y6
x1 17 43 27 14 39 52
x2 29 24 69 90 23 13
x3 18 90 62 12 16 70
x4 58 14 6 18 73 64
x5 15 41 38 36 40 60
x6 25 44 18 44 13 50

Se caută minimele de pe coloane (elementele marcate) şi se scad, rezultă:

y1 y2 y3 y4 y5 y6
x1 2 29 21 2 26 39
x2 14 10 63 78 10 0
x3 3 76 56 0 3 57
x4 43 0 0 6 60 51
x5 0 27 32 24 27 47
x6 10 30 12 32 0 37

Se caută minimul pe linii şi se scade. Teoretic se vor produce modificări doar pe liniile care nu au
nici un element zero, deoarece pe celelalte linii care au zero acesta va fi minimul şi prin scădere nu
se va modifica linia respectivă. În cazul exemplului vom modifica doar linia 1.

y1 y2 y3 y4 y5 y6
x1 -0 27 19 -0 24 37
x2 14 10 63 78 10 *0
x3 3 76 56 *0 3 57
x4 43 *0 -0 6 60 51
x5 *0 27 32 24 27 47
x6 10 30 12 32 *0 37

Etapa II:
 linia cu cele mai puţine zerouri, prima găsită:
linia 2, deci se încadrează c26,
linia 3, deci c34 (se va tăia c14),
apoi linia 5, deci c51 (se taie c11),
linia 6, deci c65.
S-a marcat cu (*) elementele încadrate şi cu (-) cele tăiate (barate).
linia 4 are 2 zerouri, se încadrează primul (c42 ) se taie al doilea (c43 )
 Toate zerourile sunt încadrate sau tăiate. Nu s-a obţinut soluţie deoarece sunt doar 5 zerouri
încadrate.
Etapa III.
Nici un zero încadrat pe linia 1; coloanele 1 şi 4, deci se marchează (conform b) de la această etapă.
Se marchează liniile 3 şi 5 (conform c), cu câte un zero încadrat.
S-au marcat: liniile: 1, 3, 5 şi coloanele: 1, 4

4
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Etapa IV.
Se elimină liniile 2, 4, 6 şi coloanele 1 şi 4 (linii nemarcate şi coloane marcate).
Se obţine:

y2 y3 y5 y6
X1 27 19 24 37
X3 76 56 3 57
X5 27 32 27 47

Etapa V.
Se caută elementul minim (3), Se scade din coloanele netăiate: 2, 3, 5, 6 şi se adună la liniile tăiate,
2, 4, 6. (caracterele italic) Se obţine:

y1 y2 y3 y4 y5 y6
x1 -0 24 16 *0 21 34
x2 17 10 63 78 10 *0
x3 3 73 53 -0 -0 54
x4 46 *0 -0 9 60 51
x5 *0 24 29 24 24 44
x6 13 30 12 35 *0 37

Se reîncepe direct cu etapa a II, pentru că pe fiecare linie minimul este zero, deci nu are rost să
exemplific etapa I, în care minimul de pe linie se scade...:
 linia cu cele mai puţine zerouri, prima găsită:
linia 2, deci se încadrează c26,
linia 5, deci c51 (se taie c11),
linia 6, deci c65. (se taie c35)
linia 1, deci c14 , deoarece c11 este tăiat (se taie c34)
linia 4, deci c42 se taie al doilea (c43 )
Deci toate zerourile sunt încadrate (*) sau tăiate (-).
Încadrate sunt 5 zerouri deci nu s-a obţinut repartiţia minimă.

Etapa III:
Se marchează linia 3 (conform a, nu are zero încadrat) şi coloanele 4 şi 5 (conform b, în linia
marcată 3 are zerouri barate). Se marchează apoi liniile 1 şi 6 (conform c, are zero încadrat în
coloanele marcate, 4,5). Apoi se marchează coloana 1 ( are zero tăiat în linia 1 marcată, conform b).
Deci s-au marcat folosind b, c:
liniile: 1, 3, 6;
coloanele: 1, 4, 5.

Etapa IV:
Se taie liniile nemarcate: 2, 4, 5 şi coloanele marcate: 1, 4, 5.

y2 Y3 y6
x1 24 16 34
x3 73 53 54
x6 30 12 37

5
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Elementul minim va fi c63=12 . Se scade 12 din coloanele netăiate (2, 3, 6) şi se adună din liniile
tăiate (2, 4, 5). Se lucrează în tabelul mare, şi se obţine:

y1 y2 y3 y4 y5 y6
x1 0 12 4 0 21 22
x2 29 10 63 93 22 0
x3 3 61 41 0 0 42
x4 58 0 0 21 72 51
x5 12 24 29 36 36 44
x6 13 18 0 35 0 25

Se reia etapa I, există linie cu toate elementele diferite de zero, linia 5 care are minimul egal cu 12.
Acest minim se va scădea din elementele liniei 5. Se va obţine:

y1 y2 y3 y4 y5 y6
x1 -0 12 4 *0 21 22
x2 29 10 63 93 22 *0
x3 3 61 41 -0 *0 42
x4 58 *0 -0 21 72 51
x5 *0 12 17 24 24 32
x6 13 18 *0 35 -0 25

Etapa II. Alegerea soluţiei optime:


 linia 2, deci c26,
 linia 5, deci c51 (se taie c11),
 linia 1, deci c14 (se taie c34),
 linia 3, deci c35 (se taie c65),
 linia 6, (are un zero nebarat, netăiat) deci c63 , (se taie c43)
 linia 4, deci c42.

S-au obţinut 6 zerouri marcate deci soluţie.


Repartiţia optimă va fi: (x1, y4), (x2, y6), (x3, y5), (x4, y2), (x5, y1), (x6, y3).
care va da valoarea minimă:
v = c14 + c26 + c35 + c42 + c51 + c63 = 14 + 13 + 16 + 14 + 15 + 18 = 90.

adică

x1 y1
14 15
x2 y2
14
13
x3 y3

x4 y4
16

x5 18 y5

x6 y6

6
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Exemplul 2: (problemă ancorată în realitate...)

În întreprinderile (x) se fabrică oricare dintre produsele (y). În funcţie de capacităţile tehnice ale
fiecărei întreprinderi preţul la desfacere diferă (conform tabloului). Dacă un produs nu se poate
realiza într-o întreprindere, elementul corespunzător va fi: -∞.

Să se realizeze repartizarea celor cinci produse pentru ca preţul total de desfacere să fie maxim.

y1 y2 y3 y4 y5
x1 -∞ 5 2 7 9
x2 3 -∞ 8 6 2
x3 7 3 -∞ 9 9
x4 8 8 11 -∞ 5
x5 3 6 4 6 -∞

Pentru a se aplica algoritmul ungar se va folosi matricea obţinută din cea iniţială în care fiecare
element este ( max din matrice minus elementul corespunzător).
Deci lucrăm cu tabloul:

y1 y2 y3 y4 y5
x1 ∞ 6 9 4 2
x2 8 ∞ 3 5 9
x3 4 8 ∞ 2 2
x4 3 3 0 ∞ 6
x5 8 5 7 5 ∞

Etapa I:
Pe fiecare coloană se caută minimul şi se scade din elementele coloanei.

y1 y2 y3 y4 y5
x1 ∞ 3 9 2 0
x2 5 ∞ 3 3 7
x3 1 5 ∞ 0 0
x4 0 0 0 ∞ 4
x5 5 2 7 3 ∞

Există liniile 2 şi 5, fără nici un element zero, se alege minimul şi la fel se scade din elementele
liniei:

y1 y2 y3 y4 y5
x1 ∞ 3 9 2 *0
x2 2 ∞ *0 -0 4
x3 1 5 ∞ *0 -0
x4 *0 -0 -0 ∞ 4
x5 3 *0 5 1 ∞

7
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Etapa II:
Se caută soluţia optimă:
 linia 1, deci c15 (se taie c35),
 linia 5, deci c52 (se taie c42),
 linia 2, deci c23 (se taie c43 şi c24),
 linia 3, deci c34,
 linia 4, deci c41.

S-au ales 5 elemente, deci soluţia a fost găsită.


Repatiţia optimă va fi: (x1, y5), (x2, y3), (x3, y4), (x4, y1), (x5, y2)
Valoarea maximă va fi:
v = c15 + c23 + c34 + c41 + c52 = 9 + 8 + 9 + 8 + 6 = 40

adică
x1 y1
9
x2 8 8 y2

x3 9 y3

x4 y4
6
x5 y5

Exemplul 3:

Din tabelul de mai jos să se extragă numere situate pe linii şi coloane diferite, astfel încât suma lor
să fie minimă.

1 2 3 4 5 6
1 2 1 3 9 5 8
2 3 4 2 0 0 6
3 0 0 6 5 3 2
4 5 4 9 8 7 5

Tabloul nefiind pătratic, algoritmul ungar nu se poate aplica. Un mod simplu este de a adăuga atâtea
linii până devine pătratic, linii cu elemente zero care nu vor influenţa rezultatul. Deci vom obţine:

1 2 3 4 5 6
1 2 1 3 9 5 8
2 3 4 2 0 0 6
3 0 0 6 5 3 2
4 5 4 9 8 7 5
5 0 0 0 0 0 0
6 0 0 0 0 0 0

8
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Etapa I:
Pe fiecare coloană există minimul 0, deci căutăm liniile care nu au elemente zero: liniile 1şi 4, unde
minimele au valorile: 1 şi 4 (coincidenţă nefericită, întâmplătoare).

1 2 3 4 5 6
1 1 *0 2 8 4 7
2 3 4 2 *0 -0 6
3 *0 -0 6 5 3 2
4 1 -0 5 4 3 1
5 -0 -0 *0 -0 -0 -0
6 -0 -0 -0 -0 *0 -0

Etapa II:
 linia 1, deci c12 (se taie c32, c42, c52, c62),
 linia 2, deci c24 (se taie c25, c54, c64),
 linia 3, deci c31 (se taie c51, c61),
 linia 5, deci c53 (se taie c55, c56, c63),
 linia 6, deci c65 (se taie c66),
Am marcat 5 elemente, deci nu avem soluţie.

Etapa III:
 se marchează linia 4 (conform a, nu are zero încadrat);
 se marchează coloana 2 (conform b, are 0 tăiat în linia 4);
 se marchează linia 1 (conform c, are 0 marcat în coloana 2)
Deci s-au marcat liniile: 1, 4 şi coloana 2.

Etapa IV:
 se taie liniile nemarcate: 2, 3, 5, 6 şi coloana marcată 2

Etapa V:
Elementul minim netăiat este 1.

1 3 4 5 6
1 1 2 8 4 7
4 1 5 4 3 1

Se scade minimul din coloanele netăiate şi se adună la liniile tăiate:

1 2 3 4 5 6
1 0 0 1 7 3 6
2 3 5 2 0 0 6
3 0 1 6 5 3 2
4 0 0 4 3 2 0
5 0 1 0 0 0 0
6 0 1 0 0 0 0

Etapa I:

9
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Nu se realizează, deoarece fiecare coloană are un zero care va fi minimul dintre elemente, deci scad
0.
Etapa II:

1 2 3 4 5 6
1 -0 *0 1 7 3 6
2 3 5 2 *0 -0 6
3 *0 1 6 5 3 2
4 -0 -0 4 3 2 *0
5 -0 1 *0 -0 -0 -0
6 -0 1 -0 -0 *0 -0

Din alegerea elementelor se poate observa că linia 2 oferă două soluţii, amândouă ar trebui să ofere
suma minimă.

Soluţia 1:
 linia 3, deci c31 (se taie c11, c41, c51, c61),
 linia 1, deci c12 (se taie c42),
 linia 2, deci c24 (se taie c25, c54, c64),
 linia 4, deci c46 (se taie c56, c66),
 linia 5, deci c53 (se taie c63),
 linia 6, deci c65

S-au ales 6 valori, deci rezultă soluţie:


Repatiţia optimă va fi: (1, 2), (2, 4), (3, 1), (4, 6) S-a ales doar soluţia, nu şi elementele introduse
prin bordarea matricei iniţiale.

Valoarea minimă a sumei va fi:


v = c12 + c24 + c31 + c46 = 1 + 0 + 0 + 5 = 6

1 2 3 4 5 6
1 -0 *0 1 7 3 6
2 3 5 2 -0 *0 6
3 *0 1 6 5 3 2
4 -0 -0 4 3 2 *0
5 -0 1 *0 -0 -0 -0
6 -0 1 -0 *0 -0 -0

Soluţia 2:
 linia 3, deci c31 (se taie c11, c41, c51, c61),
 linia 1, deci c12 (se taie c42),
 linia 2, deci c25 (se taie c24, c55, c65),
 linia 4, deci c46 (se taie c56, c66),
 linia 5, deci c53 (se taie c54, c63),
 linia 6, deci c64

S-au ales 6 valori, deci rezultă soluţie:


Repatiţia optimă va fi: (1, 2), (2, 5), (3, 1), (4, 6)
S-a ales doar soluţia, nu şi elementele introduse prin bordarea matricei iniţiale.

10
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Valoarea minimă a sumei va fi:


v = c12 + c25 + c31 + c46 = 1 + 0 + 0 + 5 = 6
Observaţie: Algoritmul ungar este diferit de Greedy.

Observaţie: Greedy în probleme de repartiţie nu oferă întotdeauna soluţia optimă. Aplicarea


algoritmului Greedy ar însemna alegerea maximului pe fiecare linie care (ţinând cont de faptul că
arcele sunt neadiacente) prin excluderea arcelor alese şi respectiv a vârfurilor nu ar conduce la
soluţia optimă.

Observaţie: Alegerea algoritmului ungar este o alegere bună şi din punct de vedere al timpului de
executare, care pentru date de test mari (p=100, q=100) are timp de executare la nivelul unei
secunde. Implementarea algoritmului necesită o muncă mai laborioasă.

În soluţia Pascal au fost comentate subprogramele în funcţie de etapele algoritmului.

Program Algoritm_Ungar;
Const NMax=500;
Fi = 'input.in';
Fo = 'output.out';

Type t_linie = array[1..NMax] of integer;


Var
a, a1 : Array [1..NMax] of ^t_linie;
LM, KM : Array [1..NMax] of Boolean;
n : Integer;
Fin, Fout : Text;

{ CITIREA DATELOR }
Procedure CitesteMatrice;
Var i, j : integer;
Begin
Assign(fin, fi);
Reset(fin);
Readln(fin, n);
For i := 1 To n Do
Begin
New(a[i]);
For j := 1 To n Do
Read(Fin, a[i]^[j]);
New(a1[i]);
a1[i]^ := a[i]^;
{ Se reţine matricea iniţială pentru rezultatele finale, deoarece
matricea a va fi modificată în fiecare etapă }
End;
Close(fin);
End;

{ ETAPA 1 }

11
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

{Pentru fiecare coloană se calculează minimul si se scade din


celelalte elemente ale coloanei respective. În matricea astfel
obţinută, se repetă procedeul, dar pentru fiecare linie.}

Procedure Etapa1;
Var i, j, min : Integer;
Begin
For i := 1 To n Do
Begin
min := a[i]^[1];
For j := 1 To n Do
If a[i]^[j] < min Then min := a[i]^[j];
For j := 1 To n Do
a[i]^[j] := a[i]^[j] - min;
End;
For j := 1 To n Do
Begin
min := a[1]^[j];
For i := 1 To n Do
If a[i]^[j] < min Then min := a[i]^[j];
For i := 1 To n Do
a[i]^[j] := a[i]^[j] - min;
End;
End;

{ ETAPA 2 }
{ Se caută o soluţie optimă:
- se alege linia cu cele mai puţine zerouri si se încadrează
unul din ele;
- se barează zerourile care se găsesc în aceeaşi linie sau în
aceeaşi coloana cu zeroul încadrat;
- se procedeaza la fel cu toate celelalte linii.
Daca nu s-a obtinut o solutie (adică au fost alese n elemenete) se
trece la ETAPA3.}

Procedure Etapa2;
Var NrZerouri, linie : integer;
NrZ : Array [1..NMax] Of Integer;

Procedure NumaraZerouri;
Var i, j : Integer;
Begin
NrZerouri := 0;
For i := 1 To n Do
Begin
NrZ[i] := 0;
For j := 1 To n Do
If a[i]^[j] = 0 Then NrZ[i] := NrZ[i] + 1;
NrZerouri := NrZerouri + NrZ[i];
End;
12
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

End;

Procedure AlegeLinie;
Var i, min : Integer;
Begin
For i := 1 To n Do
If NrZ[i] = 0 Then NrZ[i] := n + 1;
min := NrZ[1];
linie := 1;
For i := 2 To n Do
If NrZ[i] < min Then
Begin
min := NrZ[i];
linie:=i;
End;
End;

Procedure IncadreazaSiTaie;
Var k, i, j : Integer;
Begin
k := 1;
While a[linie]^[k] <> 0 Do k := k + 1;
a[linie]^[k] := -1;
{ 0 încadrat se marchează cu -1, cel tăiat cu -2}
For j := k + 1 To n Do
If a[linie]^[j] = 0 Then a[linie]^[j] := -2;
For i := 1 To n Do
If a[i]^[k] = 0 Then a[i]^[k] := -2;
End;

{ Procedura Etapa2 (programul principal al procedurii)}


Begin
NumaraZerouri;
while NrZerouri > 0 do
Begin
AlegeLinie;
IncadreazaSiTaie;
NumaraZerouri;
End;
End;

{ ETAPA 3 }
{ a)se vor marca toate liniile care nu conţin nici un zero
încadrat;
b)se va marca fiecare coloana care are unul sau mai multe
zerouri barate în una din liniile marcate;
c)se va marca fiecare linie care are un zero încadrat intr-o
coloana marcata;
d)se repeta operatiile b) si c) până când nu mai este posibil
să se obţină alte linii sau coloane marcate.}

Procedure Etapa3;
13
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Var NrMarcaje : Integer;

Procedure InitMarcaj;
Var i:Integer;
Begin
For i := 1 To n Do
KM[i] := false;
End;

Procedure MarcLFaraZIncadrat;
Var i, j : Integer;
Begin
For i := 1 To n Do
Begin
LM[i] := true;
For j := 1 To n Do
If a[i]^[j] = -1 Then LM[i] := false;
End;
NrMarcaje := 0;
For i := 1 To n Do
If LM[i] { = TRUE } Then NrMarcaje := NrMarcaje + 1;
End;

Procedure MarcKCuZTaiat;
Var i, j : Integer;
Begin
NrMarcaje := 0;
For j := 1 To n Do
If not KM[j] Then
For i := 1 To n Do
If LM[i] And (a[i]^[j] = -2) Then
Begin
KM[j] := true;
NrMarcaje := NrMarcaje + 1;
End;
End;

Procedure MarcLCuZIncadrat;
Var i, j : Integer;
Begin
NrMarcaje := 0;
For i := 1 To n Do
If not LM[i] Then
For j:= 1 To n Do
If KM[j] And(a[i]^[j] = -1) Then
Begin
LM[i] := true;
NrMarcaje := NrMarcaje + 1;
End;
End;

{ Procedura Etapa3 - program principal}


14
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Begin
InitMarcaj;
MarcLFaraZIncadrat;
While NrMarcaje > 0 Do
Begin
MarcKCuZTaiat;
If NrMarcaje > 0 Then
MarcLCuZIncadrat;
End;
End;

{ ETAPA 4 }
{ Se evidenţiază fiecare linie nemarcată si fiecare coloana
marcată.
În matricea elementelor care nu au fost evidenţiate, se va
alege minimul.
Se scade acest minim din elementele coloanelor neevidenţiate şi
se va aduna la elementele liniilor evidenţiate.
Cu matricea astfel obţinută se repetă procedeul(toate etapele)
până se va obţine soluţia optimă.}

Procedure Etapa4;
Var LT, KT : array [1..NMax] of Boolean;
i, j, min : Integer;
Begin
For i:= 1 To n Do
Begin
LT[i] := not LM[i];
KT[i] := KM[i];
End;
min := MaxInt;
For i := 1 To n Do
If not LT[i] Then
For j := 1 To n Do
If not KT[j] Then
If a[i]^[j] < min Then min := a[i]^[j];
For i := 1 To n Do
For j := 1 To n Do
Begin
If a[i]^[j] < 0 Then a[i]^[j] := 0;
If LT[i] AND KT[j] Then
a[i]^[j] := a[i]^[j] + min
Else
If not LT[i] And not KT[j] Then
a[i]^[j] := a[i]^[j] - min;
End;
End;

{ TESTUL DE OPTIM }
Function SolutieOptima : Boolean;
15
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Var i, j, NrZI : Integer;


Begin
NrZI := 0;
For i := 1 To n Do
For j := 1 To n Do
If a[i]^[j] = -1 Then
NrZI := NrZI + 1;
If nrZI = n Then
SolutieOptima := true
Else
SolutieOptima := false
End;

{ AFISARE REZULTAT }

Procedure AfiseazaSolutie;
Var i, j : Integer;
total : LongInt;
Begin
Assign(fout, fo);
ReWrite(fout);
total := 0;
For i := 1 To n Do
For j := 1 To n Do
If a[i]^[j] = -1 Then
Begin
WriteLn(Fout, a1[i]^[j]);
total := total + a1[i]^[j];
End;
WriteLn(Fout, total);
Close(Fout);
End;

{ PROGRAMUL PRINCIPAL }

Begin
CitesteMatrice;
Etapa1;
Etapa2;
While not SolutieOptima Do
Begin
Etapa3;
Etapa4;
Etapa2;
End;
AfiseazaSolutie;
End.

16
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Încercaţi aplicarea Algoritmului ungar pentru


Exemplul 3:

Colonii pe Marte (problemă propusă de autori la E-Mail Informatics Contest în 1998)

În anul 2003, pe planeta Marte s-a terminat construcţia unei "oaze", în care viaţa oamenilor putea fi
posibilă. În vederea colonizării, fiecare ţară de pe glob, a trimis un reprezentant. Ştiind că, pentru a
transporta un individ se foloseşte câte un avion special şi că fiecare deplasare are un cost bine
stabilit, dat intr-o matrice de forma:

C[i,j] = costul transportului persoanei i, folosind avionul j,

se cere să se determine o repartiţie a persoanelor pe avioane, astfel încât costul total de transport să
fie minim.

Intrare:
Datele de intrare se citesc din fişierul MARTE.IN, având structura:

n // pe prima linie numarul de indivizi;


c11 c12 c13 ... c1n // pe urmatoarele n linii costurile corespunzatoare
c21 c22 c23 ... c2n // deplasarilor, numere naturale cuprinse intre
... // 1 si 255, separate prin spatiu;
cn1 cn2 cn3 ... cnn // 0 < n < 100;

Ieşire:
Datele de ieşire se scriu în fişierul MARTE.OUT, având structura:

c1 i1 // reprezentând pe primele n linii costurile


// ck ik 1 <= k <= n; 1 <= ik <= n
c2 i2 // ce realizează minimul cerut, precum şi
c3 i3 // pe ultima linie valoarea acestui minim
...
cn in
min // min = c1 i1 + c2 i2 + ... + cn in

Exemplu:

MARTE.IN MARTE.OUT
6 27
17 43 27 14 39 52 13
29 24 69 90 23 13 16
18 90 62 12 16 70 14
58 14 6 18 73 64 15
15 41 38 36 40 60 18
25 44 18 44 13 50 90

17
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

Pentru problema dată a fost propusă o soluţie care se apropie de algoritmul Greedy:
{$A+,B-,D+,E-,F-,G-,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+}

Var a,c: Array[1..100,1..100] of Byte;


x,y: Array[1..100] of Integer;
f,ff: Array[1..100] of Boolean;
ii,i,j,n: Integer;
fi,fo: Text;
min,mi: Integer;
Flag,fl: Boolean;
Op,co,pr: Integer;

Begin
Assign(fi,'MARTE.IN'); Reset(fi);
Readln(fi, n);
For i:=1 to n do
Begin min:=256;
For j:=1 to n do
Begin Read(fi,c[i,j]);
If c[i,j]<min Then Begin
min:=c[i,j]; y[i]:=j
{ se calculeaza minimul pe fiecare linie si se retine in vectorul
y care este coloana pentru care s-a asigurat minimul}
End
End;
Inc(x[y[i]]); Readln(fi);
{ x este un vector care sesizeaza de cate ori a fost folosita o
coloana pentru minim, este solutie daca x este format doar din
valori 1 }
End;
Close(fi);
a:=c; Flag:=true;

While Flag do
Begin
f:=ff;
j:=1;
While (j<=n) and (x[j]<=1) do Inc(j);
{ caut prima pozitie care are valoare mai mare ca 1, adica o coloana
folosita de mai multe ori, in continuare se cauta o alta coloana
pentru linia respectiva care sa conduca la acelasi minim pe care
l-am realizat prima data }
If j>n Then Flag:=false;
If Flag Then Begin
f[j]:=true; fl:=true;
While fl do
Begin
mi:=256;
For i:=1 to n do
if f[y[i]] Then
Begin
min:=256;
For j:=1 to n do
if not(f[j]) and (a[i,j]<min) Then
Begin min:=a[i,j]; co:=j End;
if mi>min-a[i,y[i]] Then
Begin mi:=min-a[i,y[i]];
ii:=i; pr:=co End;

18
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

If mi=0 then Break


End;
If mi>0 Then For j:=1 to n do
If f[j] then for i:=1 to n do
Inc(a[i,j],mi);
If x[pr]=0 Then
Begin op:=y[ii]; y[ii]:=pr; fl:=false;
Dec(x[op]); Inc(x[pr]) End
Else f[pr]:=true;
End;
End
End;

Assign(fo,'MARTE.OUT'); Rewrite(fo);
min:=0;
For i:=1 to n do
Begin writeln(fo,c[i,y[i]]); Inc(min,c[i,y[i]]) End;
Writeln(fo,min);
Close(fo);
End.

Pentru fişierul de intrare dat ca exemplu, algoritmul realizează următoarele:


 calculează valoarea minimă pentru fiecare linie (va reţine primul minim găsit), va reţine în
vectorul y[linie]=coloana, (linie, coloana) fiind poziţia minimului pe linia respectivă.
 calculează şi frecvenţa de apariţie a unei coloane, vectorul x[coloana]=număr de apariţii în
vectorul y.
 dacă vectorul x este format din valori 1 pe cele n poziţii atunci soluţia problemei poate fi scrisă
în fişier, aaceasta fiind formată din valorile a[i, y[i]]. i=1, n.
Deci pentru datele de intrare, vom avea n=6; matricea c:

17 43 27 14 39 52
29 24 69 90 23 13
18 90 62 12 16 70
58 14 6 18 73 64
15 41 38 36 40 60
25 44 18 44 13 50

vectorul y={ 4, 6, 4, 3, 1, 5}, iar vectorul x={1, 0, 1, 2, 1, 1}


Pentru lucru, se copiază matricea c într-o matrice a.
 se cauta în vectorul x prima valoare mai mare ca 1 (prima coloana folosită de mai multe ori)
 pe liniile care folosesc aceste colaone se va căuta următoare valoare minimă diferită de cea
găsită, mar astfel încât diferenţa dintre minime să fie cât mai mică posibil.
Deci pe prima linie se va determina următorul minim egal cu 17 (pe prima coloană), diferenţa dintre
acest minim şi valoarea 14 (minimul pe acestă linie) este 3. Se adună valoarea 3 la coloana
minimului. Se va obţine:

17 43 27 17 39 52
29 24 69 93 23 13
18 90 62 15 16 70
58 14 6 21 73 64
15 41 38 39 40 60

19
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

25 44 18 47 13 50

Coloana 1 este folosită pentru minimul de pe linia 5.


Următorul minim pe linia 1 este 27, pe coloana 3 (diferenţa dintre acest minim şi minimul real al
liniei 1, care se găseşte pe coloan 1 şi pe coloan 4, este 10), pe linia 3 următorul minim este 16 , pe
coloana 5 (diferenţa dintre acest minim şi minimul real este 1). Deci va fi ales ultimul minim. Se
adaugă la coloan 1 şi la coloana 3 diferenţa 1. Coloanele folosite se marchează în vectorul f, prin
valoarea „true”

18 43 27 18 39 52
30 24 69 94 23 13
19 90 62 16 16 70
59 14 6 22 73 64
16 41 38 40 40 60
26 44 18 48 13 50

Vectorul f={ true, false, false, true, true, false}


De pe liniile marcate se alege valoarea minimă şi se reţine aceea care realizeză diferenţa faţă de
minimul real cea mai mică posibil. Se adună valoarea 5 (diferenţa minimă obţinută la pasul anterior)
coloanelor 1, 4, 5.

23 43 27 23 44 52
35 24 69 99 28 13
24 90 62 21 21 70
64 14 6 27 78 64
21 41 38 45 45 60
31 44 18 53 18 50

Vectorul f={ true, false, true, true, true, false}. Următoare valoare minimă creaza diferenţa egală cu
8, care se va aduna la coloanele 1, 3, 4, 5. Se va obţine:

31 43 35 31 52 52
43 24 77 107 36 13
32 90 70 29 29 70
72 14 14 35 86 64
29 41 46 53 53 60
39 44 26 61 26 50

Se caută minimele pe linii:

31 43 35 31 52 52
43 24 77 107 36 13
32 90 70 29 29 70
72 14 14 35 86 64
29 41 46 53 53 60
39 44 26 61 26 50

deci y={4, 6, 4, 2, 1, 3 } iar vectorul x={1, 1, 1, 2, 0, 1 }, şi deoarece pe linia 3 există un alt minim
de aceeşi valoare de pe o coloană nefolosită se va alege acesta. Deci se va obţine:

20
Algoritmul ungar prof. Maria şi Adrian NIŢĂ

31 43 35 31 52 52
43 24 77 107 36 13
32 90 70 29 29 70
72 14 14 35 86 64
29 41 46 53 53 60
39 44 26 61 26 50

y={ 4, 6, 5, 2, 1, 3} iar x={1, 1, 1, 1, 1, 1} ceea ce conduce la o soluţie.


Elementele c [i, y[i]] vor forma soluţia minimă.

21

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