HEAPSORT

Se da un vector de numere intregi. Sa se ordoneze crescator valorile din vector.

Fisier de intrare: sort.in
Linia 1: n - numarul de elemente din vector
Linia 2: A1 - elementul 1 din vector
...
Linia n+1: An - elementul n din vector

Fisier de iesire: sort.out
Linia 1: S1 ... Sn
unde S este sirul A sortat crescator

Restrictii
-30000<=A1, ..., An<=30000
1<=n<=30000

Analiza problemei

Am studiat mai multi algoritmi de sortare. Cel mai cunoscut dintre acestia este BubbleSort, care este studiat primul in clasa a IX-a. Dupa cum se stie, complexitatea cu care acesta sorteaza datele de intrare este de O(n^2) in cel mai defavorabil caz.

Alti algoritmi simpli studiati in clasa a IX-a care ruleaza in aceeasi complexitate sunt: InsertSort (sortarea prin inserare), SelectSort (sortarea prin selectarea minimului/maximului). Cel mai avantajos algoritm de sortare este MathSort (sortare prin numarare) care ruleaza in O[n+D], unde D este dimensiunea spatiului de valori. Din pacate acest algoritm poate fi aplicat pentru domenii reduse de valori.

Ulterior, au fost studiati si alti algoritmi de sortare mai eficienti: QuickSort (sortare rapida) care in medie are complexitatea O(n log n) dar in cazul cel mai defavorabil ajunge la O(n^2), MergeSort ( sortare prin interclasare ) care are complexitatea O(n log n) dar necesita o structura de date suplimentara care ar putea constitui o problema in ceea ce priveste spatiul disponibil.

Pentru o complexitate mai buna (sau cel putin la fel de buna) si fara a necesita structuri de date suplimentare putem folosi algoritmul de sortare cu heap-uri, denumit si HeapSort. Astfel, datele din vectorul de intrare sunt organizate initial sub forma unui heap. La fiecare pas se extrage radacina (fiind mutata eventual pe pozitia care se elibereaza in procesul extragerii) si se reorganizeaza sub forma de heap vectorul obtinut printr-o operatie de combinare de heap-uri. Complexitatea acestui algoritm va fi O(n log n). Procedura de organizare a vectorului in heap a fost analizata la capitolul Creare Heap: O(n). La fiecare pas se reorganizeaza heap-ul in complexitate O(log n). Astfel, algoritmul propriu-zis ruleaza in complexitate O(n log n).
Pentru o intelegere mai buna a acestui algoritm puteti urmari o simulare animata.

SIMULARE

ARBORE PARTIAL DE COST MINIM

Fie G=(V, U) un graf neorientat si c: U->R+ o functie prin care se asociaza fiecarei muchii o valoare reala pozitiva numita costul muchiei. Sa se determine un arbore partial (graf partial conex si aciclic) de cost minim al grafului G. Prin costul unui arbore se intelege suma costurilor muchiilor din arbore.

Fisier de intrare: apm.in
Linia 1: n m - numarul de noduri, respectiv numarul de muchii din graf
Linia 2: X1 Y1 C1- exista muchie intre nodurile X1 si Y1 de cost C1;
...
Linia m+1: Xm Ym C1- exista muchie intre nodurile Xm si Ym de cost Cm;

Fisier de iesire: apm.out
Linia 1: S1 D1
...
Linia n-1: S(n-1) D(n-1)
unde Si Di reprezinta descrierea muchiei i din arbore.

Analiza problemei

Pentru a determina arborele partial de cost minim al unui graf au fost studiati doi algoritmi fundamentali: algoritmul lui Prim si algoritmul lui Kruskal. Vom analiza complexitatea celui de-al doilea algoritm si modul in care il putem optimiza utilizand un heap.
Algoritmul lui Kruskal implica selectarea de n-1 ori (unde n reprezinta numarul de varfuri din graf) a unei muchii de cost minim, care nu formeaza cicluri cu cele deja selectate. O prima idee ar fi sa sortam muchiile dupa cost, apoi sa selectam in ordine n-1 muchii care nu formeaza cicluri. Complexitatea algoritmului va fi egala cu complexitatea algoritmului de sortare, deci in cazul unui algoritm de sortare eficient O(m log m) (unde cu m am notat numarul de muchii din graf, care poate fi de ordinul lui n^2), la care se adauga complexitatea algoritmului de construire a arborelui partial (O(n)*numarul de operatii necesare pentru a retine evidenta componentelor conexe). Evidenta componentelor conexe este necesara pentru a testa daca o muchie formeaza sau nu cicluri cu cele deja selectate.
O prima optimizare a acestui algoritm se poate realiza observand ca nu este necesar sa sortam muchiile. Este necesara o structura de date care sa ne permita sa selectam eficient n-1 muchii de cost minim. Pentru aceasta, vom organiza muchiile ca un heap (complexitatea acestei operatii fiind O(m)). In etapa de constructie a arborelui partial vom extrage succesiv muchii de cost minim, complexitatea operatiei de extragere fiind O(log m). Observati ca facand aceasta optimizare am redus deja complexitatea algoritmului la O(m)+O(n log m) * nr de operatii necesare pentru a retine evidenta componentelor conexe.
Observati ca nu am determinat complexitatea operatiei de evidenta a componentelor conexe. Aceasta este O(n) daca retinem intr-un vector evidenta componentelor conexe sau O(log n) daca retinem evidenta componentelor conexe cu ajutorul unor arbori, implementand eficient operatiile union-find.

Implementarea algoritmului Kruskal cu organizarea muchiilor ca heap. Vizualizare sursa. Salvare sursa.

APLICATII PROPUSE

1. Fie G=(V, U) un graf neorientat si c: U->R+ o functie prin care se asociaza fiecarei muchii o valoare reala pozitiva numita costul muchiei. Fie x0 si y0 doua varfuri din graf. Sa se determine drumul de cost minim dintre cele doua varfuri date. Prin costul unui drum se intelege suma costurilor muchiilor ce apartin drumului.

Fisier de intrare: drum.in
Linia 1: n m - numarul de noduri, respectiv numarul de muchii din graf
Linia 2: X1 Y1 C1- exista muchie intre nodurile X1 si Y1 de cost C1;
...
Linia m+1: Xm Ym Cm- exista muchie intre nodurile Xm si Ym de cost Cm;
Linia m+2: S D - cele doua varfuri pentru care trebuie calculat drumul minim.

Fisier de iesire: drum.out
Linia 1: C - costul drumului minim.

Indicatie: Folositi algoritmul lui Dijkstra optimizand cautarea valorii minime la un anumit pas. Pentru a putea extrage minimul in timp [log n] organizati vectorul de valori temporare ca un heap.

 

2. Se da un sir de numere intregi si doua numere X si Y. Sa se determine subsecventa de suma maxima a carei lungime se afla in intervalul [X,Y].

Fisier de intrare: secv.in
Linia 1: n - numarul de elemente din sir
Linia 2: A1 - elementul 1 din sir
...
Linia n+1 - An - elementul n din sir.

Fisier de iesire: secv.out
Linia 1: Smax - Suma maxima ceruta.

Indicatie: Calculati sumele Si = A1+A2+...+Ai. Observam ca suma oricarei subsecvente poate fi scrisa ca o diferenta intre doua elemente din S (Exemplu: Suma subsecventei [2..5] = S5-S1). La pasul i consideram ca trebuie o subsecventa care sa se termine in i si care are suma maxima. Pentru a calcula maximul putem alege Y-X+1 subsecvente diferite. Organizati sumele acestor subsecvente intr-un heap pentru extragerea maximului.

3. Urgenta (Olimpiada Judeteana de informatica 2002)

Autoritatile dintr-o zona de munte intentioneaza sa stabileasca un plan de urgenta, pentru a reactiona mai eficient la frecventele calamitati naturale din zona. In acest scop au identificat n puncte de interes strategic si le-au numerotat distinct de la 1 la n. Punctele de interes strategic sunt conectate prin m cai de acces avand prioritati in functie de importanta. Intre oricare doua puncte de interes strategic exista cel mult o cale de acces ce poate fi parcursa in ambele sensuri si cel putin un drum (format din una sau mai multe cai de acces) ce le conecteaza.
In cazul unei calamitati unele cai de acces pot fi temporar intrerupte si astfel intre anumite puncte de interes nu mai exista legatura. Ca urmare, pot exista mai multe grupuri de puncte in asa fel incat intre oricare doua puncte din acelasi grup sa existe macar un drum si intre oricare doua puncte din grupuri diferite sa nu existe drum.
Autoritatile estimeaza gravitatea unei calamitati ca fiind suma prioritatilor cailor de acces distruse de aceasta si doresc sa determine un scenariu de gravitate maxima, in care punctele de interes strategic sa fie impartite intr-un numar de k grupuri.

Fisier de intrare: urgenta.in
n m k
i1 j1 P1 - intre punctele i1 si j1 exista cale de acces de prioritate P1
i2 j2 P2 - intre punctele i2 si j2 exista cale de acces de prioritate P2
...
im jm Pm - intre punctele im si jm exista cale de acces de prioritate Pm

Fisier de iesire: urgenta.out
gravmax - gravitatea maxima
C - numarul de cai de acces intrerupte de calamitate
k1 h1 - intre punctele k1 si h1 a fost intrerupta calea de acces
k2 h2 - intre punctele k2 si h2 a fost intrerupta calea de acces
...
kC hC - intre punctele kC si hC a fost intrerupta calea de acces

Restrictii si precizari
- 0<n<256
- n-2<m<32285
- 0<k<n+1
- prioritatile cailor de acces sunt intregi strict pozitivi mai mici decat 256
- un grup de puncte poate contine intre 1 si n puncte inclusiv
- daca exista mai multe solutii, programul va determina una singura.
- timp maxim de executie: 1 secunda / test

Exemplu

urgenta.in
7 11 4
1 2 1
1 3 2
1 7 3
2 4 3
3 4 2
3 5 1
3 6 1
3 7 5
4 5 5
5 6 4
6 7 3

urgenta.out
27
8
1 3
1 7
2 4
3 4
3 7
4 5
5 6

6 7


Graful din exemplu:graful din exemplu

Heap Interactiv :: Contact ::