Didaxis
lecție · Informatică

Algoritmii Kruskal și Prim

Construirea unui arbore parțial minim.

Se face în:
Clasa a XI-a
Actualizat la: 30 octombrie 2026
1pe scurtstratul 1 din 2 · rezumatul lecției

Pe scurt

Kruskal și Prim caută un arbore parțial de cost minim într-un graf neorientat conex ponderat. Kruskal examinează muchiile în ordine crescătoare a costului și le ia dacă nu formează ciclu. Prim pornește de la un vârf și adaugă cea mai ieftină muchie care leagă arborele construit de un vârf din afară.

Desen la lecția „Algoritmii Kruskal și Prim”
2în detaliustratul 2 din 2 · pentru clasă și Bacalaureat

În detaliu

Algoritmii Kruskal și Prim determină un arbore parțial de cost minim al unui graf neorientat conex ponderat, adică muchii care unesc toate vârfurile cu suma costurilor cea mai mică. Ambii sunt greedy: la fiecare pas aleg muchia cea mai ieftină permisă. Kruskal sortează muchiile crescător după cost și le adaugă pe rând, dacă nu formează ciclu cu cele alese; verificarea se face rapid cu o structură de mulțimi disjuncte, în care două vârfuri sunt în aceeași componentă dacă au aceeași rădăcină. Prim pornește dintr-un vârf și, la fiecare pas, adaugă cea mai ieftină muchie care leagă arborele construit de un vârf din afara lui. Pentru un graf deconectat nu există arbore parțial care să cuprindă toate vârfurile. Dacă există ponderi egale, pot exista arbori minimi diferiți, dar toți au același cost minim.

Graful are patru vârfuri și muchiile [1,2]:1, [2,3]:2, [3,4]:3, [1,3]:4, [1,4]:8.

Exemplul 1 — Kruskal. Muchiile sunt deja în ordinea crescătoare a costurilor:

#include <iostream>
using namespace std;
int t[5];
int rad(int x) { return t[x] == x ? x : t[x] = rad(t[x]); }
int main() {
    int e[5][3] = {{1, 2, 1}, {2, 3, 2}, {3, 4, 3}, {1, 3, 4}, {1, 4, 8}};
    int cost = 0;
    for (int i = 1; i <= 4; ++i) t[i] = i;
    for (auto& m : e) {
        int a = rad(m[0]), b = rad(m[1]);
        if (a == b) {
            cout << "respins " << m[0] << "-" << m[1] << "\n";
            continue;
        }
        t[a] = b;
        cost += m[2];
        cout << m[0] << "-" << m[1] << "\n";
    }
    cout << cost;
}

Se afișează 1-2, 2-3, 3-4, apoi respins 1-3 și respins 1-4, iar costul este 6. Primele trei muchii leagă toate vârfurile și însumează . Muchia [1,3] este respinsă, deoarece ar închide ciclul 1–2–3–1, iar [1,4] este respinsă, deoarece 1 și 4 sunt deja în aceeași componentă. Sortarea muchiilor dă pentru Kruskal timp.

Exemplul 2 — Prim cu matrice. Se menține pentru fiecare vârf din afara arborelui costul d[v] al celei mai ieftine muchii către arbore și vârful tata[v] de care se leagă. Se alege vârful cu d minim, se adaugă la arbore și se actualizează vecinii lui:

#include <iostream>
using namespace std;
int main() {
    const int INF = 1000000, n = 4;
    int c[5][5], d[5], tata[5] = {}, in[5] = {}, cost = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j) c[i][j] = INF;
    c[1][2] = c[2][1] = 1; c[2][3] = c[3][2] = 2; c[3][4] = c[4][3] = 3;
    c[1][3] = c[3][1] = 4; c[1][4] = c[4][1] = 8;
    for (int i = 1; i <= n; ++i) d[i] = INF;
    d[1] = 0;
    for (int pas = 1; pas <= n; ++pas) {
        int u = 0;
        for (int i = 1; i <= n; ++i)
            if (!in[i] && (u == 0 || d[i] < d[u])) u = i;
        in[u] = 1;
        cost += d[u];
        if (tata[u]) cout << tata[u] << "-" << u << " ";
        for (int v = 1; v <= n; ++v)
            if (!in[v] && c[u][v] < d[v]) { d[v] = c[u][v]; tata[v] = u; }
    }
    cout << "\n" << cost;
}

Se afișează 1-2 2-3 3-4, apoi 6. Din vârful 1 frontiera are muchiile [1,2]:1, [1,3]:4 și [1,4]:8, deci se alege [1,2]. Din cea mai ieftină muchie către exterior este [2,3]:2; din este [3,4]:3. Arborele rezultat are costul 6, ca la Kruskal. Cu matrice, Prim folosește timp.

Exemplul 3 — în formatul examenului. Un graf cu 5 vârfuri are muchiile [1,2]:3, [1,3]:5, [2,3]:1, [2,4]:4, [3,4]:2, [3,5]:6 și [4,5]:7. Care este costul unui arbore parțial de cost minim?

  • a) 10
  • b) 12
  • c) 13
  • d) 15

Răspunsul corect este b). Kruskal ia [2,3]:1 și [3,4]:2, apoi [1,2]:3. Muchia [2,4]:4 este respinsă, fiindcă 2 și 4 sunt deja unite prin 3, iar [1,3]:5 este respinsă, fiindcă 1 și 3 sunt deja unite prin 2. Muchia [3,5]:6 leagă vârful 5. Costul este , cu 4 muchii. Varianta a) adună și acceptă [2,4], care închide ciclul 2–3–4. Varianta c) leagă vârful 5 prin [4,5]:7, mai scump decât [3,5]:6. Varianta d) adună primele cinci costuri, , fără să verifice ciclurile.

Exemplul 4 — ponderi egale. Graful are vârfurile 1, 2, 3 și muchiile [1,2]:1, [2,3]:1, [1,3]:1. Kruskal ia primele două muchii din ordinea sortării, iar a treia este respinsă, deoarece 1 și 3 sunt deja în aceeași componentă. Orice pereche de două muchii formează un arbore parțial, deci există trei arbori minimi diferiți, toți cu costul .

Greșeli frecvente

  • Greșit: Kruskal acceptă orice muchie ieftină chiar dacă produce ciclu.
    Corect: respinge muchiile care închid un ciclu.
  • Greșit: Prim poate alege o muchie între două vârfuri încă neincluse.
    Corect: muchia aleasă trebuie să traverseze frontiera arborelui curent.
  • Greșit: două implementări trebuie să dea exact aceleași muchii la ponderi egale.
    Corect: pot exista arbori minimi diferiți.
în contul tăuPremium

Testează-te pe această lecție

Lecția o citești aici, fără cont. Testele pe lecții și capitole sunt în cont, cu grile originale Didaxis și explicația fiecăreia: gratuit 10 grile pe zi, fără limită cu Premium, 49 de lei pe lună pentru fiecare copil.

Înainte și după

Surse și referințe

Redactare proprie, conform programei:

  • OMECI 5099/2009, anexa 5, Informatică, p. 4–5, clasa XI intensiv; rocnee.eu

Documente consultate

  • Programa școlară de informatică intensiv, clasa a XI-a (OMECI 5099/2009, anexa 5), CNCE, p. 4–5; rocnee.eu
  • OpenDSA, capitolul „Minimal Cost Spanning Trees”, secțiunile „Prim's Algorithm” și „Kruskal's Algorithm”, opendsa.cs.vt.edu/OpenDSA/Books/Catalog/html/MCST.html

Desene: Redactare proprie (desen original)

lecțiile sunt gratuite

Ai citit lecția. Acum verifică-te.