====== Probleme "dificile" ====== În acest laborator veți explora un graf realist cu date despre toate aeroporturile din lume și rutele dintre ele și veți aplica diverși algoritmi *eficienți* pe acesta. Momentan, puteți considera termenul "eficient" să însemne "fără backtracking" (mai precis, ne referim la conceptul de polinomial, i.e. cu o complexitate descrisă de $ O(n^k)$, pentru un $ k$ natural; vom relua conceptul la curs). Descărcați de aici arhiva cu datele de intrare: {{:aa:lab:lab.zip|}} Aceasta conține în directorul ''res/'' trei fișiere cu date despre aeroporturi și rute: - ''airroutes.in'' - din lume \\ - ''eu-airroutes.in'' - din Europa \\ - ''ro-airroutes.in'' - din România Fișierele descriu grafuri orientate, ale căror noduri au ID-uri întregi începând de la 0; respectă următorul format: - pe prima linia, numărul de noduri ''N'' și numărul de muchii din graf, separate de un spațiu. \\ - pe următoarele ''N'' linii, informații despre un nod \\ - pe linia ''i'' (probabil indexată de la 1 în editorul de text), găsiți informații despre nodul cu ID ''i - 2'': \\ - [[https://www.iata.org/en/publications/directories/code-search/|codul IATA]] al aeroporturlui \\ - toate rutele de la acel aeroport exprimate folosind trei numere: ID-ul aeroportului destinație, distanța zborului în kilometri, durata zborului în minute. Fișierele sunt doar o versiune parser-friendly a datelor din acest JSON: https://github.com/Jonty/airline-route-data/blob/main/airline_routes.json În ''tools/extract_c_friendly.py'' găsiți scriptul care a realizat extragerea. ==== Exerciții ==== 1. Scrieți un program care parsează un fișier de intrare cu formatul descris și reține graful în memorie. Programul apoi primește un singur cod IATA al unui aeroport(de la ''stdin'' sau ca argument în linia de comandă), determină toți vecinii și printează codurile lor IATA pe o singură linie separate de câte un spațiu. 2. Scrieți un program cu același input ca mai sus dar care scrie ''N'' linii într-un fișier: pentru fiecare aeroport, linia corespunzătoare ID-ului trebuie să conțină codul IATA urmat de numărul minim de noduri prin care se poate ajunge acolo (pentru aeroportul de referință primit ca input, printați "-" în loc de număr, iar pentru aeroporturile la care nu se poate ajunge printați "unreachable"). BONUS: folosiți [[https://web.stanford.edu/class/archive/cs/cs161/cs161.1182/Lectures/Lecture11/CS161Lecture11.pdf|algoritmul lui Djikstra]] pentru a calcula cea mai scurtă rută din punct de vedere al distanței și al timpului (scrieți rezultatele în fișiere diferite). 3. Care sunt cele mai îndepărtate aerporturi de OTP pentru fiecare metrică? Dar de LHR (London Heathrow)? Care e cea mai mare distanță posibilă între oricare două aeroporturi, pentru fiecare metrică? Care este cel mai izolat aeroport, pentru fiecare metrică? (aeroportul cu cea mai mare distanță medie către toate celelalte aeroporturi) 4. Determinați toate componentele conexe ale grafului folosind BFS sau DFS la alegere. Scrieți componentele într-un alt fișier de output, câte una pe linie; fiecare componentă conexă e descrisă de codurile IATA a tuturor aeroporturilor din care e formată, separate de un spațiu. 5. Creați un graf neorientat pe baza grafului inițial. Vom crea muchii neorientate doar între acele aeroporturi între care există muchii în ambele sensuri (pentru weight, folosiți media celor două muchii orientate). Determinați dacă există o clică de dimensiune 20 în graful rezultat. Dar de 30? Folosiți o căutare exhaustivă de forma: - inițializați o mulțime goală \\ - la fiecare pas: \\ - adăugați un nod (e.g. următorul în ordinea ID) în mulțime; dacă nu mai sunt noduri, reveniți la pasul anterior \\ - verificați dacă mulțimea e clică; dacă nu, înapoi la pasul anterior \\ - verificați dacă sunt $ k$ elemente în mulțime; dacă nu, treceți la pasul următor; altfel printați clica Scrieți clica într-un fișier separat într-un format similar cu al fișierelor ''*.in''. BONUS: încercați să implementați orice fel de euristică ce ar grăbi procesarea (în general, sau pe anumite tipuri de grafuri), **păstrând însă garanția că răspunsul întors este cel corect**. 6. Scrieți un alt program care citește un graf neorientat complet dintr-un fișier (clica anterioară) și rezolvă problema comisului voiajor (Traveling Salesman Problem), prin căutare exhaustivă. Încercați grafuri mici întâi și încercați să determinați cât timp durează rularea în funcție de numărul de noduri.