Cod sursa(job #3272194)

Utilizator AndreeaHzmAndreea Huzum AndreeaHzm Data 28 ianuarie 2025 20:17:37
Problema Arbore partial de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.31 kb
//Complexitate: O(M log N), unde M este numărul de muchii și N este numărul de noduri

#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream fin("apm.in");
ofstream fout("apm.out");

class Graf {
private:
    int nrNoduri; // Numărul de noduri din graf
    vector<pair<int, pair<int, int>>> muchii; // Vector de muchii, fiecare cu formatul (cost, (nod1, nod2))

public:
    Graf(int nrNoduri);

    void citireMuchii(int nrMuchii);

    void kruskalAPM();

private:
    int reprezentant(int nod, vector<int> &tata);

    void uneste(int tataSursa, int tataDestinatie, vector<int> &tata, vector<int> &inaltime);
};

Graf::Graf(int nrNoduri) {
    this->nrNoduri = nrNoduri;
}

void Graf::citireMuchii(int nrMuchii) {
    int sursa, destinatie, cost;
    // Citirea muchiilor
    for (int i = 1; i <= nrMuchii; i++) {
        fin >> sursa >> destinatie >> cost;
        muchii.push_back({cost, {sursa, destinatie}});
    }
}

int Graf::reprezentant(int nod, vector<int> &tata) {
    // Funcție recursivă pentru a găsi reprezentantul (rădăcina) unui nod
    if (tata[nod] != nod)
        tata[nod] = reprezentant(tata[nod], tata); // Comprimare drum (path compression)
    return tata[nod];
}

void Graf::uneste(int tataSursa, int tataDestinatie, vector<int> &tata, vector<int> &inaltime) {
    // Unirea a două subarbori pe baza înălțimii
    if (inaltime[tataSursa] > inaltime[tataDestinatie]) {
        tata[tataDestinatie] = tataSursa;
    } else if (inaltime[tataSursa] < inaltime[tataDestinatie]) {
        tata[tataSursa] = tataDestinatie;
    } else {
        tata[tataDestinatie] = tataSursa;
        inaltime[tataSursa]++;
    }
}

void Graf::kruskalAPM() {
    vector<pair<int, int>> apm; // Muchiile care vor face parte din APM
    vector<int> tata(nrNoduri + 1); // Vector pentru părinți
    vector<int> inaltime(nrNoduri + 1, 0); // Vector pentru înălțimea arborilor
    int costTotal = 0;

    // Inițializare: fiecare nod este reprezentant pentru sine
    for (int i = 1; i <= nrNoduri; i++) {
        tata[i] = i;
    }

    // Sortăm muchiile crescător după cost
    sort(muchii.begin(), muchii.end());

    // Procesăm fiecare muchie
    for (auto &muchie: muchii) {
        int cost = muchie.first;
        int nod1 = muchie.second.first;
        int nod2 = muchie.second.second;

        // Găsim reprezentanții celor două noduri
        int tata1 = reprezentant(nod1, tata);
        int tata2 = reprezentant(nod2, tata);

        // Dacă nodurile nu fac parte din același arbore, le unim
        if (tata1 != tata2) {
            uneste(tata1, tata2, tata, inaltime);
            apm.push_back({nod1, nod2}); // Adăugăm muchia în APM
            costTotal += cost; // Adăugăm costul muchiei la costul total
        }
    }

    // Afișăm rezultatul
    fout << costTotal << "\n"; // Costul total al APM
    fout << apm.size() << "\n"; // Numărul de muchii din APM
    for (auto &muchie: apm) {
        fout << muchie.first << " " << muchie.second << "\n"; // Muchiile din APM
    }
}

int main() {
    int nrNoduri, nrMuchii;
    fin >> nrNoduri >> nrMuchii;

    Graf g(nrNoduri);
    g.citireMuchii(nrMuchii);
    g.kruskalAPM();

    fin.close();
    fout.close();
    return 0;
}