Cod sursa(job #2944932)

Utilizator AncaGAncuta Gava AncaG Data 23 noiembrie 2022 09:19:54
Problema Paduri de multimi disjuncte Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.28 kb
#include<bits/stdc++.h>
using namespace std;

ifstream file_input("disjoint.in");
ofstream file_output("disjoint.out");

// am situatia initiala cand nodurile sunt proprii lor parinti (atatea multimi cate noduri)
// construiesc aceste seturi
// am nevoie de rangul asociat fiecarui nod astfel incat sa am un criteriu (pt reuniunea dupa rang)
// complexitate:  pentru o operatie de tipul 2, O(log*N)-->log*N inversa functiei Akermann (valorile functiei cres rapid la 2 la 65536−3, inversa avand propr opusa)
//  si O(1) pt tipul 1

class Graf_disjoint {
private:
    int operatie, nod1, nod2;
    // nr de noduri si nr de muchii
    int n, m;

    // trebuie sa memorez parintele (parintele imi va spune daca nodurile sunt din acelasi set)
    vector<int> parinti;

    // trebuie sa am rangul per nod (el imi va pune cum sa fac reuniunea)
    vector<int> ranguri;


public:
    void input_graf();
    int find_Parent(int nod);
    void join_Nodes(int u, int v);
    void intersect_Nodes(int u, int v);
};

void Graf_disjoint::input_graf() {
    file_input >> n >> m;
    parinti.resize(n+1);
    ranguri.resize(n+1);


    for(int i=1 ; i <= n; i++){
        // fiecare nod e propriul sau parinte
        parinti[i] = i;
        // initial toate nodurile au rangul 0 , sunt pe picior de egalitate
        ranguri[i] =0;
    }

    for (int i = 1; i <= m; ++i){
        file_input>> operatie>>nod1>>nod2;
        if (operatie ==  1) join_Nodes(nod1, nod2);
        else
            intersect_Nodes(nod1, nod2);
    }
}

// inainte sa unesc noduri trebuie sa stabilesc parintele fiecarui nod
int Graf_disjoint::find_Parent(int nod) {
    // daca nodul este propriul sau parinte il returnez
    if(nod == parinti[nod]){
        return nod;
    }

    // indiferent altfel merg pe calea stramosilor si apelez recursiv pe parintele sau pana cand
    // ajung la parintele suprem
    return parinti[nod] = find_Parent(parinti[nod]);
}

void Graf_disjoint::join_Nodes(int u, int v) {
    // inainte de join tr sa stiu de parintele fiecarui nod
    // lucrezi cu parintii mai departe din u respectiv v

    int parinte_u, parinte_v;
    parinte_u = find_Parent(u);
    parinte_v = find_Parent(v);

    // cand am relatia parinte copil nu e nevoie de update pe graduri
    // fiindca e deja descoperit din conditie
    if(ranguri[parinte_u] < ranguri[parinte_v]){
        parinti[parinte_u] = parinte_v;
    }else if (ranguri[parinte_v] < ranguri[parinte_u]){
        parinti[parinte_v] = parinte_u;
    } else {
    // aici sunt pe picior de egalitate si imi este indiferent cum pun parintele
    // am pastrat la fel cu conditia de mai sus
    // aici gresc si gradul fiindca trebuie sa discriminez parintele de copil
        parinti[parinte_v] = parinte_u;
        ranguri[u] ++;
    }

}

void Graf_disjoint::intersect_Nodes(int u, int v) {
    if (parinti[u] == parinti[v]){
        file_output<< "DA"<<"\n";
        // trebuie sa am si partea de pattern compression (legand toate nodurile de parintele suprem)
    } else if (find_Parent(v) == parinti[u]) {
        file_output << "DA" << "\n";
    }
    else{
        file_output<< "NU"<<"\n";
    }
}


int main(){
    Graf_disjoint my_graf;
    my_graf.input_graf();

}