Rezultatele rundei a treiaRunda 3 Problema 1 Blocaje (ruperea conexității)Problema se reduce la determinarea numărului minim de muchii care trebuie eliminate pentru ca un graf neorientat să nu fie conex. Punctajul mediu obținut de concurenți la această problemă a fost de 43,97 puncte, o medie acceptabilă având în vedere dificultatea destul de ridicată a problemei. Mulți concurenți au fost dezorientați de faptul că în enunț nu erau precizate limite pentru datele de intrare. De data aceasta nu a fost o greșeală a redacției, omisiunea fiind intenționată, deoarece la multe concursuri (printre care și ACM) asemenea limite nu sunt precizate întotdeauna. Datele de test au fost "la limita bunului simț", neexistând cazuri în care numărul de orașe să depășească 100, deci nu ar fi trebuit să apară probleme la memorarea grafului. Vă prezentăm în continuare soluția propusă de Cristian Alexandrescu, din Botoșani. Având două noduri diferite s și t ale grafului, pentru a le deconecta trebuie să înlăturăm un număr minim de muchii care este egal cu numărul maxim de drumuri disjuncte (ca muchii) dintre s și t (teorema este asemănătoare cu teorema lui Menger, demonstrația fiind similară dacă se folosește teorema flux maxim/tăietură de capacitate minimă: Într-o rețea de transport tăietura minimă este egală cu fluxul maxim.). Pentru determinarea numărului de drumuri disjuncte (ca muchii) dintre s și t, se folosește algoritmul Edmonds-Karp, aplicat pe o rețea de transport, obținută prin înlocuirea fiecărei muchii a grafului inițial printr-o pereche de arce simetrice, fiecare dintre aceste arce având capacitatea 1. Un flux de valoare maximă, definit pe această rețea, reprezintă numărul maxim de drumuri disjuncte (ca muchii) dintre s și t. Aparent, ar trebui să aplicăm algoritmul pentru flux maxim pentru oricare două noduri i și j ale grafului și să alegem valoarea minimă dintre toate valorile obținute pentru fluxul maxim. De fapt, este suficientă aplicarea algoritmului Edmonds-Karp de n-1 ori pentru rețeaua de transport având intrarea s un nod oarecare (fixat) iar ieșirea (t) fiind orice nod din rețeaua de transport diferit de s. Acest lucru este dovedit de faptul că, înlăturând oricare muchii care îndeplinesc condiția din enunț (că deconectează cel puțin două vârfuri) va fi deconectată intrarea s de cel puțin un vârf care, la un moment dat va fi ieșire pentru algoritmul de determinare a fluxului maxim. Muchiile care trebuie înlăturate reprezintă o tăietură de valoare minimă în rețeaua pentru care s-a obținut valoarea minimă a fluxului maxim. Deoarece algoritmul Edmonds-Karp este aplicat de n-1 ori, ordinul de complexitate al algoritmului prezentat anterior poate fi obținut adăugând factorul n la ordinul de complexitate al algoritmului Edmonds-Karp (O(m2- n)). Obținem astfel un ordin de complexitate O(m2- n2). Algoritmul descris a fost implementat astfel:
Runda 3 Problema 2 Numere primeA fost aceasta cea mai dificilă problemă? Nici unul dintre concurenți nu a reușit să obțină mai mult de 80 de puncte; punctajul mediu a fost și el destul de mic și anume 35.16 puncte. Au existat cel puțin două motive pentru care a fost propusă această problemă. În primul rând, în numărul 7/99 al GInfo a apărut un articol care trata verificarea primalității numerelor mari, deci am vrut să vedem dacă ați citit articolul. De asemenea, am dorit să încurajăm implementarea algoritmilor folosind limbajul Java, limbaj care oferă (prin intermediul metodei isProbablePrime() a clasei BigInteger) posibilitatea testării directe a primalității numerelor mari. Din nefericire, puținii concurenți care au ales să folosească limbajul Java au comis unele erori și punctajele obținute au fost surprinzător de mici. Majoritatea programatorilor în C și Pascal au rezolvat corect problema din punct de vedere logic, dar algoritmii nu au fost suficient optimizați și pentru numere foarte mari programele au depășit limita de timp admisă. O altă eroare frecvent întâlnită a fost verificarea primalității numerelor 0 și 1 pe care mulți concurenți le-au considerat prime, chiar dacă din exemplul publicat reieșea clar că numărul 1 nu este prim. Nu vă putem prezenta soluția propusă de un anumit concurent, deoarece nu a existat nici o rezolvare corectă. Din aceste motive am decis să publicăm soluția oficială care a fost implementată folosind limbajul Java. Metoda isProbablePrime() a clasei BigInteger are un argument care indică numărul de teste efectuate pentru verificarea primalității numărului. Fiecare test are o probabilitate de eroare de 1/2. Efectuând mai multe teste, probabilitatea de eroare scade exponențial, pentru n teste, ea devenind 1/2n. Datorită faptului că programele sunt rulate pe un calculator Intel Pentium III cu frecvența de 450 MHz, valoarea n aleasă poate fi destul de mare, chiar și efectuarea a 100 de verificări încadrându-se în limita de timp (10 secunde/test - 1 secundă/număr). Totuși, chiar și 10 verificări ar fi fost suficiente, probabilitatea de eroare în acest caz fiind mai mică de 1. Runda 3 Problema 3 JocDin reacțiile concurenților rezultă că, probabil aceasta a fost cea mai interesantă problemă propusă până în prezent la concursul Bursele Agora; au existat și participanți care au afirmat că aceasta este cea mai interesantă problemă de informatică pe care au întâlnit-o vreodată. Punctajul mediu obținut a fost de 47.03 puncte. Datorită multitudinii de cazuri care trebuie tratate era aproape imposibil ca cineva să rezolve problema pentru toate configurațiile posibile. Fiecare concurent a găsit diverse configurații pentru tabla de joc în funcție de anumite caracteristici ale dimensiunilor m și n. În final, se pare că cel mai bine s-a descurcat Mihai Stroe din București care a obținut cel mai mare punctaj. Virgil Șerbănuță din București a obținut punctaje maxime pentru 18 din cele 20 de teste, dar celelalte două configurații indicate de el nu respectau condițiile date, motiv pentru care nu a obținut nici un punct la aceste teste. Vă prezentăm în continuare implementarea propusă de Adrian Cârcu din Bistrița (90 puncte): [cuprins] |