This shows you the differences between two versions of the page.
|
sd-ca:laboratoare:lab-08 [2026/05/11 21:55] valentin.carauleanu [Sortarea topologică] |
sd-ca:laboratoare:lab-08 [2026/05/11 22:09] (current) valentin.carauleanu [Interviu] |
||
|---|---|---|---|
| Line 4: | Line 4: | ||
| * [[stef.dascalu@gmail.com|Ștefan-Teodor Dascălu]] | * [[stef.dascalu@gmail.com|Ștefan-Teodor Dascălu]] | ||
| * [[melih.riza03@gmail.com|Melih Riza]] | * [[melih.riza03@gmail.com|Melih Riza]] | ||
| + | * [[valentin.carauleanu@stud.fim.upb.ro|Cărăuleanu Valentin Gabriel]] | ||
| ===== Obiective ===== | ===== Obiective ===== | ||
| Line 106: | Line 107: | ||
| Pentru a reține distanța și drumul exact de la ''A'' la ''B'', se păstrează pentru fiecare nod: | Pentru a reține distanța și drumul exact de la ''A'' la ''B'', se păstrează pentru fiecare nod: | ||
| - | * ''d[x]'' — distanța de la sursă la nodul ''x'' | + | * ''d[x]'' - distanța de la sursă la nodul ''x'' |
| - | * ''p[x]'' — părintele lui ''x'' în drumul de la sursă spre ''x'' | + | * ''p[x]'' - părintele lui ''x'' în drumul de la sursă spre ''x'' |
| În momentul descoperirii unui nod ''y'' al cărui părinte este ''x'', se fac atribuirile: | În momentul descoperirii unui nod ''y'' al cărui părinte este ''x'', se fac atribuirile: | ||
| Line 176: | Line 177: | ||
| Sortarea topologică se realizează printr-o parcurgere **DFS**, în care se rețin pentru fiecare nod: | Sortarea topologică se realizează printr-o parcurgere **DFS**, în care se rețin pentru fiecare nod: | ||
| - | * ''tDesc[u]'' — momentul descoperirii nodului ''u'' | + | * ''tDesc[u]'' - momentul descoperirii nodului ''u'' |
| - | * ''tFin[u]'' — momentul finalizării procesării nodului ''u'' | + | * ''tFin[u]'' - momentul finalizării procesării nodului ''u'' |
| La final, nodurile sunt sortate **descrescător** după ''tFin''. Nodul care se finalizează cel mai târziu trebuie să apară primul în sortare, deoarece nu depinde de niciun alt nod nedescoperit încă. | La final, nodurile sunt sortate **descrescător** după ''tFin''. Nodul care se finalizează cel mai târziu trebuie să apară primul în sortare, deoarece nu depinde de niciun alt nod nedescoperit încă. | ||
| Line 310: | Line 311: | ||
| ==== Ciclu hamiltonian ==== | ==== Ciclu hamiltonian ==== | ||
| - | Un lanţ hamiltonian într-un graf orientat sau neorientat ''G = (V, E)'', este o cale ce trece prin fiecare nod din ''V'' o singură dată. Dacă nodul de început şi cel de sfârşit coincid (este vizitat de două ori) vom spune că lanţul formează un **ciclu hamiltonian**. | + | Un **lanț hamiltonian** într-un graf orientat sau neorientat ''G = (V, E)'' este o cale ce trece prin fiecare nod din ''V'' o singură dată. Dacă nodul de început și cel de sfârșit coincid, lanțul formează un **ciclu hamiltonian**. |
| - | Un graf ce conţine un ciclu hamiltonian se numeşte graf hamiltonian. | + | Un graf ce conține un ciclu hamiltonian se numește **graf hamiltonian**. |
| + | |||
| + | <note important> | ||
| + | Problema găsirii unui ciclu hamiltonian este **NP-completă**, ceea ce înseamnă că nu se cunoaște niciun algoritm eficient (polinomial) pentru cazul general. | ||
| + | </note> | ||
| === Algoritm === | === Algoritm === | ||
| - | În cadrul acestui laborator, vom folosi metoda backtracking pentru găsirea unui ciclu hamiltonian. Pentru contruirea soluţiei, se menţine o listă în care sunt adăugate nodurile parcurse: | + | În cadrul acestui laborator, vom folosi metoda **backtracking** pentru găsirea unui ciclu hamiltonian. Se menține o listă în care sunt adăugate nodurile parcurse: |
| + | |||
| + | * La fiecare pas, se adaugă unul dintre nodurile care nu se află deja în listă. | ||
| + | * Se construiește recursiv lanțul de ''lungime_lant + 1''. | ||
| + | * Dacă dimensiunea listei este ''n'', se verifică dacă există o muchie de la ultimul nod din listă către primul. Dacă nu există o astfel de muchie, lanțul curent nu poate fi închis într-un ciclu hamiltonian și se continuă cu backtracking. | ||
| + | * Pentru a afla **toate** ciclurile hamiltoniene, la revenirea din apelul recursiv nu se iese din funcție la prima potrivire, ci se încearcă în continuare alte posibilități. | ||
| + | |||
| + | === Complexitate === | ||
| - | * La fiecare pas, vom adăuga unul dintre nodurile care nu se află deja in listă | + | ^ Complexitate ^ Valoare ^ |
| - | * Se construieşte recursiv lanţul de lungime_lanţ + 1 | + | ^ **Timp** | ''O(|V|!)'' în cazul cel mai defavorabil | |
| - | * Dacă dimensiunea listei este ''n'' (numărul de noduri din graf), se verifică dacă primul şi ultimul nod din listă sunt adiacente. În caz contrar, s-a găsit un lanţ hamiltonian, dar nu şi un ciclu hamiltonian. | + | ^ **Spațiu** | ''O(|V|)'' pentru stiva de recursivitate și lanț | |
| - | * Pentru a afla toate ciclurile hamiltoniene, la revenirea cu succes din apelul recursiv nu se iese din funcţie la găsirea primei potriviri, ci se încearcă în continuare alte posibilităţi. | + | |
| === Pseudocod === | === Pseudocod === | ||
| Line 327: | Line 338: | ||
| <code> | <code> | ||
| // Inițializări | // Inițializări | ||
| - | număr_noduri = număr de noduri din V | + | numar_noduri = număr de noduri din V |
| - | // Verifica dacă un nod este nou în lanţ | + | // Verifică dacă un nod este nou în lanț |
| - | nouÎnLanţ(nod, lanţ) | + | nouInLant(nod, lant) |
| { | { | ||
| - | return !lanţ.conţine(nod) | + | return !lant.contine(nod) |
| } | } | ||
| - | // Construieste lanţul hamiltonian | + | // Construiește lanțul hamiltonian |
| - | construireLanţ(lanţ, lungime_lanţ) | + | construireLant(lant, lungime_lant) |
| { | { | ||
| - | dacă lungime_lanţ == număr_noduri | + | dacă lungime_lant == numar_noduri |
| { | { | ||
| - | început = lanţ[0] | + | inceput = lant[0] |
| - | sfârşit = ultimul element din lanţ | + | sfarsit = ultimul element din lant |
| - | + | // Verifică dacă există muchie de la sfarsit spre inceput | |
| - | // Există muchie între cele 2 noduri | + | dacă muchie(sfarsit, inceput) |
| - | dacă muchie(început, sfârşit) | + | |
| { | { | ||
| - | // Lanţul este ciclu | + | afiseaza ciclul |
| - | afişează ciclul | + | |
| return true | return true | ||
| } | } | ||
| Line 355: | Line 364: | ||
| pentru orice nod u din V | pentru orice nod u din V | ||
| { | { | ||
| - | sfârşit = ultimul element din lanţ | + | sfarsit = ultimul element din lant |
| - | dacă muchie(u, sfârşit) şi nouÎnLanţ(u, lanţ) | + | // Verifică dacă există muchie de la sfarsit spre u |
| + | dacă muchie(sfarsit, u) si nouInLant(u, lant) | ||
| { | { | ||
| - | addLast(lanţ, u) // Adaugă u la lanţ | + | addLast(lant, u) // Adaugă u la lanț |
| - | + | ||
| - | construireLanţ(lanţ, lungime_lanţ + 1) | + | |
| - | // Pentru afişarea unui singur ciclu hamiltonian linia anterioară este inlocuită cu: | + | construireLant(lant, lungime_lant + 1) |
| - | // dacă construireLanţ(lanţ, lungime_lanţ + 1) == true | + | // Pentru afișarea unui singur ciclu hamiltonian, |
| - | // return true | + | // linia anterioară se înlocuiește cu: |
| - | + | // dacă construireLant(lant, lungime_lant + 1) == true | |
| - | removeLast(lanţ, u) // Backtrack | + | // return true |
| + | |||
| + | removeLast(lant, u) // Backtrack | ||
| } | } | ||
| } | } | ||
| Line 374: | Line 384: | ||
| // Apelează construirea ciclurilor hamiltoniene | // Apelează construirea ciclurilor hamiltoniene | ||
| - | cicluriHamiltoniene | + | cicluriHamiltoniene() |
| { | { | ||
| - | // Din moment ce ar trebui să formeze un ciclu, lanţul poate incepe cu orice nod | + | // Din moment ce formează un ciclu, lanțul poate începe cu orice nod |
| - | sursă = alegem un nod aleator din V | + | sursa = alegem un nod aleator din V |
| - | addLast(lanţ, sursă) | + | addLast(lant, sursa) |
| - | construireLanţ(lanţ, 1) | + | construireLant(lant, 1) |
| } | } | ||
| </code> | </code> | ||
| - | |||
| === Exemplu === | === Exemplu === | ||
| - | {{sd-ca:laboratoare:hamilton.png}} | + | {{sd-ca:laboratoare:hamilton.png?400}} |
| - | + | ||
| ===== Exerciții ===== | ===== Exerciții ===== | ||
| <note> | <note> | ||
| - | Trebuie să vă creați cont de [[https://code.devmind.ro/ | Devmind]], dacă nu v-ați creat deja, pe care îl veți folosi la SD pe toată durata semestrului. Aveti grija sa selectati contestul corect la submit, si anume **[[https://beta.lambdachecker.io/contest/34 |SD-CA-LAB-11 Grafuri (Advanced) ]]** | + | Trebuie să vă creați cont de [[https://code.devmind.ro/|Devmind]], dacă nu v-ați creat deja, pe care îl veți folosi la SD pe toată durata semestrului. |
| </note> | </note> | ||
| 1) [**3.5p**] Rezolvați problema **Connected Components**. | 1) [**3.5p**] Rezolvați problema **Connected Components**. | ||
| + | 2) [**3.5p**] Rezolvați problema **Minimum Path**. | ||
| + | 3) [**3p**] Rezolvați problema **Check Bipartite**. | ||
| + | ===== Interviu ===== | ||
| - | 2) [**3.5p**] Rezolvați problema **Minimum Path**. | + | Această secțiune nu este punctată și încearcă să vă ofere o idee despre tipurile de întrebări pe care le puteți întâlni la un job interview din materia prezentată în cadrul laboratorului. |
| + | === Probleme recomandate === | ||
| - | 3) [**3p**] Rezolvati problema **Check Bipartite**. | + | **Sortare topologică:** |
| + | * [[https://leetcode.com/problems/course-schedule-ii/description|210. Course Schedule II]] (returnarea ordinii topologice efective) | ||
| + | * [[https://leetcode.com/problems/longest-increasing-path-in-a-matrix/description|329. Longest Increasing Path in a Matrix]] (DAG implicit pe matrice) | ||
| + | **Componente conexe și grafuri bipartite:** | ||
| + | * [[https://leetcode.com/problems/is-graph-bipartite/description|785. Is Graph Bipartite?]] (verificare bipartitivitate cu BFS/DFS) | ||
| + | * [[https://leetcode.com/problems/accounts-merge/description|721. Accounts Merge]] (componente conexe cu Union-Find) | ||
| + | * [[https://leetcode.com/problems/satisfiability-of-equality-equations/description|990. Satisfiability of Equality Equations]] (componente conexe pe graf implicit) | ||
| + | **Drumuri minime:** | ||
| + | * [[https://leetcode.com/problems/network-delay-time/description|743. Network Delay Time]] (Dijkstra clasic) | ||
| + | * [[https://leetcode.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/description|1334. Find the City with the Smallest Number of Neighbors]] (Floyd-Warshall) | ||
| + | * [[https://leetcode.com/problems/cheapest-flights-within-k-stops/description|787. Cheapest Flights Within K Stops]] (Bellman-Ford cu constrângeri) | ||
| + | **Probleme avansate:** | ||
| + | * [[https://leetcode.com/problems/reconstruct-itinerary/description|332. Reconstruct Itinerary]] (circuit eulerian pe graf orientat) | ||
| + | * [[https://leetcode.com/problems/critical-connections-in-a-network/description|1192. Critical Connections in a Network]] (punți în graf cu algoritmul Tarjan) | ||
| + | * [[https://leetcode.com/problems/swim-in-rising-water/description|778. Swim in Rising Water]] (BFS/Dijkstra pe matrice cu cost variabil) | ||
| ===== Bibliografie ===== | ===== Bibliografie ===== | ||