Diferente pentru problema/apm intre reviziile #24 si #38

Nu exista diferente intre titluri.

Diferente intre continut:

h2. Date de ieşire
Fisierul de iesire $apm.out$ va contine pe prima linie costul arborelui partial de cost minim.
Fisierul de iesire $apm.out$ va contine pe prima linie costul arborelui partial de cost minim. Pe a doua linie se va gasi numarul de muchii din arborele partial selectat. Fiecare din urmatoarele linii, pana la sfarsitul fisierului de iesire, va contine cate doua numere naturale, capetele unei muchii ce apartine arborelui solutie. Muchiile pot fi afisate in orice ordine. Daca sunt mai multe solutii corecte se poate afisa oricare.
h2. Restricţii
* $1 ≤ N ≤ 200.000$
* $1 ≤ M ≤ 400.000$
* $-1.000 ≤ C ≤ 1.000$
* Pentru $20%$ din teste $N,M ≤ 20$
* Pentru inca $20%$ din teste $N ≤ 800$ si $M ≤ 1.500$.
* $1 ≤ N ≤ 200 000$
* $1 ≤ M ≤ 400 000$
* $-1 000 ≤ C ≤ 1 000$
* Pentru $20%$ din teste $N, M ≤ 20$
* Pentru inca $20%$ din teste $N ≤ 800$ si $M ≤ 1 500$
h2. Exemple
8 7 5
8 9 4
9 7 3
6 7 11€
|37|3 3
6 7 11
|37
8
3 1
7 9
7 3
9 8
7 4
2 1
5 2
7 6|3 3
1 2 -3
2 3 -4
3 1 -5|-9|
3 1 -5|-9
2
1 3
3 2|
h3. Explicatii
h2. Indicaţii de rezolvare
O prima idee ar fi generarea tuturor submultimilor de $N-1$ muchii, verificarea daca muchiile selectate formeaza un arbore si retinerea solutiei optime. Aceasta rezolvare este cea mai evidenta si are complexitatea $O(2^N^*N)$ si obtine aproximativ $20$ de puncte.
Presupunand ca sunt deja alese $N-2$ muchii care nu formeaza cicluri, in alte cuvinte formeaza $2$ arbori, trebuie sa se mai aleaga inca o muchie, este evident ca trebuie sa se aleaga muchia minima care garanteaza conectivitatea arborilor. De la aceasta idee deducem ca cel mai bine ar fi sa adaugam muchii de cost minim, cat timp aceste muchii nu creaza cicluri.
Deci daca se sorteaza muchiile si se parcurg in ordinea sortarii, ne este mereu util sa bagam muchia minima cat timp aceasta nu creaza un cicluri. Aceasta solutie are complexitate $O(N*M + Mlog{~2~}M)$, deoarece iterarea prin cele $M$ muchii are complexitate {$O(M)$}, iar parcurgerea dfs pentru verificarea ciclurilor este {$O(N)$}. O astfel de solutie se poate vedea 'aici':job_detail/229653?action=view-source si ar trebui sa ia $40-50$ de puncte, depinzand de implementare.
Parcurgerea dfs este redundanta, deoarece verificarea daca $2$ noduri, cele pe care le leaga muchia, sunt in aceeasi grupa se poate face in $O(log{~2~}N)$ cu 'multimi disjuncte':/problema/disjoint. Astfel complexitatea se reduce la $O(M*log{~2~}N + M*log{~2~}M)$ pentru ca se alege fiecare muchie si pentru fiecare muchie se verifica in $O(log{~2~}N)$ utilitatea ei.Pentru o optimizare mai departe se pot apela diferite metode de sortare care se bazeaza pe inexactitatea reprezintarii numerelor in calculator. De obicei nu trebuie optimizata sortarea. O reprezentare grafica se poate gasi "aici":http://en.wikipedia.org/wiki/Kruskal%27s_algorithm. Acest algoritm se numeste Kruskal si implementarea sa se poate vedea 'aici':job_detail/229317?action=view-source.
Pentru a intelege o alta solutie se presupune urmatorul scenariu: Existand deja calculat un subarbore minim vrem sa introducem in el inca un nod. Evident vom introduce nodul care are muchia minima care il leaga de subarborele deja format. Aceasta solutie are complexitate $O(N*M)$, deoarece incepem cu un nod aleator si iterand tot adaugam inca cate un nod, pana sunt toate adaugate. Pentru a vedea nodul cu muchie minima parcurgem cele M muchii. Acest algoritm se poate optimiza, daca pentru fiecare nod se tine muchia  minima curenta care il leaga de subarborele existent. La fiecare introducere a unui nod in subarbore, se actualizeaza toti vecinii lui.Aceasta solutie are complexitate $O(N^2^)$ si ar trebui sa obitna $50$ puncte.
Pentru a se optimiza mai departe algoritmul pentru extragerea minimului se foloseste un "heap":http://en.wikipedia.org/wiki/Heap_(data_structure) , iar de fiecare data cand se introduce un nod in subarbore sunt parcurse muchiile lui si actualizate nodurile. Astfel complexitatea devine $O(M*log{~2~}N)$, o optimizare semnificativa fata de Kruskal, acest algoritm se numeste "Prim":http://en.wikipedia.org/wiki/Prim%27s_algorithm. O sursa implementata se poate vedea "aici":job_detail/229651?action=view-source.
 
O prima idee ar fi generarea tuturor submultimilor de $N-1$ muchii, verificarea daca muchiile selectate formeaza un arbore si retinerea solutiei optime. Aceasta rezolvare este cea mai evidenta dar are complexitate exponentiala si obtine aproximativ $20$ de puncte.
Presupunand ca sunt deja alese $N-2$ muchii care nu formeaza cicluri, in alte cuvinte formeaza $2$ arbori, trebuie sa se mai aleaga inca o muchie, si anume muchia minima care garanteaza conectivitatea arborilor. De la aceasta idee deducem ca cel mai bine ar fi sa adaugam muchii de cost minim, cat timp aceste muchii nu creaza cicluri.
Daca se sorteaza muchiile crescator dupa costul asociat si se parcurg in ordinea sortarii, este mereu util sa adaugam la solutie muchia de cost minim cat timp aceasta nu creaza un ciclu, sau altfel spus, nodurile pe care le uneste nu sunt deja in aceeasi componenta conexa. Aceasta solutie are complexitate $O(N*M + Mlog{~2~}M)$, deoarece iterarea prin cele $M$ muchii are complexitate {$O(M)$}, iar 'parcurgerea dfs':problema/dfs pentru verificarea ciclurilor se realizeaza in timp {$O(N)$} la fiecare pas. O astfel de solutie obtine 40-50 de puncte, in functie de implementare, si se poate vedea 'aici':job_detail/234746?action=view-source.
Pentru a optimiza solutia de mai sus este suficient la fiecare pas sa verificam daca cele doua noduri pe care le uneste muchia curenta sunt in aceeasi componenta conexa, operatie care se poate realiza in timp {$O(log*N)$}, cu ajutorul 'multimilor disjuncte':problema/disjoint. Astfel complexitatea se reduce la $O(Mlog*N + Mlog{~2~}M)$. Acest algoritm este prezentat si "aici":http://en.wikipedia.org/wiki/Kruskal%27s_algorithm si se numeste algoritmul lui Kruskal. O implementare pe aceasta idee se gaseste 'aici':job_detail/234736?action=view-source.
Pentru a intelege o alta solutie se presupune urmatorul scenariu: existand deja calculat un subarbore minim vrem sa introducem in el inca un nod. Evident vom introduce nodul care are muchia de cost minim care il leaga de subarborele deja format. Aceasta solutie are complexitate $O(N*M)$, deoarece incepem cu un nod aleator si adaugam rand pe rand toate nodurile ramase. Acest algoritm se poate optimiza, daca pentru fiecare nod se tine muchia minima curenta care il leaga de subarborele existent. La fiecare introducere a unui nod in subarbore, se actualizeaza toti vecinii lui. Aceasta solutie are complexitate $O(N^2^)$ si ar trebui sa obtina $50$ puncte. Trebuie in plus precizat ca in cazul in care graful este dens (numarul de muchii $M$ este de ordinul {$O(N^2^)$}) aceasta abordare este de preferat celor cu alte complexitati.
Pentru a se optimiza mai departe algoritmul pentru extragerea minimului se foloseste un {"heap":http://en.wikipedia.org/wiki/Heap_(data_structure)}, iar de fiecare data cand se introduce un nod in subarbore sunt parcurse muchiile incidente cu el si se actualizeaza nodurile vecine. Astfel complexitatea devine $O(M*log{~2~}N)$. Algoritmul este cunoscut in literatura de specialitate ca "Algoritmul lui Prim":http://en.wikipedia.org/wiki/Prim%27s_algorithm. O sursa pe acesta idee se poate vedea 'aici':job_detail/234741?action=view-source.
h2. Aplicatii

Nu exista diferente intre securitate.

Diferente intre topic forum:

 
3509