Cod sursa(job #2801903)

Utilizator TDV24Tont Dragos-Valentin TDV24 Data 17 noiembrie 2021 04:09:36
Problema Paduri de multimi disjuncte Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 9.69 kb
#include <bits/stdc++.h>

using namespace std;

class Graf {
private:
    int nr_noduri;
    int nr_muchii;
    vector<vector <int>> lista_vecini;

public:
    Graf();

    Graf(int nr_noduri, int nr_muchii);

    ~Graf();

    vector<vector<int>> getlista_vecini();

    void graf_neorientat(istream &fis_sursa);

    void graf_orientat(istream &fis_sursa);

    void graf_orientat_DFS(istream &fis_sursa);

    void DFS(int nod, vector<bool> &vizitat);

    int comp_conexe();

    void BFS(int nod, ostream &fis_destinatie);

    void hakimi(int noduri, vector<int> &lista, ostream &fis_destinatie);

    int DFS_sortaret(queue<int> &ordine);

    void DFS_biconex(int nod, int nivel_actual, vector<int> &nivel, vector<int> &nivel_minim, vector<bool> &vizitat, stack<int> &stiva, vector<vector<int>> &subgraf_biconex);

    int disjoint_gasit(int a, vector<int> &v);

    void disjoint_uneste(int a, int b, vector<int> &v, vector<int> &rang);
};
    Graf::Graf()
    {
        nr_noduri = 0;
        nr_muchii = 0;
    }

    Graf::Graf(int nr_noduri_fis, int nr_muchii_fis)
    {
        vector<int> v(1,-1);
        nr_noduri = nr_noduri_fis;
        nr_muchii = nr_muchii_fis;
        for(int i = 1; i <= nr_noduri; i++)
            lista_vecini.push_back(v);
    }
    Graf::~Graf()
    {
        nr_noduri = 0;
        nr_muchii = 0;
        lista_vecini.clear();
    }

    vector<vector<int>> Graf::getlista_vecini()
    {
        return lista_vecini;
    }

    void Graf::graf_neorientat(istream &fis_sursa)
    {
        int a, b;
        for(int i = 1; i <= nr_muchii; i++)
        {
            fis_sursa >> a >> b;
            lista_vecini[a].push_back(b);
            lista_vecini[b].push_back(a);
        }
    }

    void Graf::graf_orientat(istream &fis_sursa)
    {
        int a, b;
        for(int i = 1; i <= nr_muchii; i++)
        {
            fis_sursa >> a >> b;
            lista_vecini[a-1].push_back(b-1);
        }
    }

    void Graf::graf_orientat_DFS(istream &fis_sursa)
    {
        int a, b;
        for(int i = 1; i <= nr_muchii; i++)
        {
            fis_sursa >> a >> b;
            lista_vecini[a].push_back(b);
        }
    }

    void Graf::DFS(int nod, vector<bool> &viz)
    {
        viz[nod] = 1;
        for(int i = 1; i < lista_vecini[nod].size(); i++)
            if(viz[lista_vecini[nod][i]] == 0)
                DFS(lista_vecini[nod][i], viz);
    }

    int Graf::comp_conexe()
    {
        int nr = 0;
        vector<bool> viz(nr_noduri + 1, 0);
        for(int i = 1; i <= nr_noduri; i++)
            if(!viz[i])
            {
                nr++;
                DFS(i, viz);
            }
        return nr;
    }

    void Graf::BFS(int nod, ostream &fis_destinatie)
    {
        int a;
        queue<int> coada;
        vector<int> dist(nr_noduri, -1);
        dist[nod-1] = 0;
        coada.push(nod-1);
        while(!coada.empty())
        {
            a = coada.front();
            coada.pop();
            for(auto& i: lista_vecini[a])
                if(dist[i] == -1)
                {
                    dist[i] = dist[a] + 1;
                    coada.push(i);
                }
        }
        for(int i = 0; i < nr_noduri; i++)
            fis_destinatie << dist[i] << " ";
    }

    void Graf::hakimi(int noduri, vector<int> &lista, ostream &fis_destinatie)
    {
        int cond = 0;
        while(cond == 0)
        {
            sort(lista.begin(), lista.end(), greater<>());
            if ( lista[0] == 0)
                cond = 1;
            cout<<lista[0]<<" ";
            int aux = lista[0];
            lista.erase(lista.begin() + 0);

            if(aux > lista.size())
                cond = -1;
            for(int i = 0; i < aux; i++)
                {
                    lista[i]--;
                    if(lista[i] < 0)
                        cond = -1;
                }
        }
        if(cond == 1)
            fis_destinatie << "DA\n";
        else
            fis_destinatie << "NU\n";
    }

    int Graf::DFS_sortaret(queue<int> &lista)
    {
        queue<int> nod_grade;
        vector<int> grade_interne(100005, 0);
        for(int i = 1; i <= nr_noduri; i++)
            for(int j = 1; j < lista_vecini[i].size(); j++)
                grade_interne[lista_vecini[i][j]] += 1;
        for(int i = 1; i <= nr_noduri; i++)
            if(grade_interne[i] == 0)
                nod_grade.push(i);
        while(!nod_grade.empty())
        {
            int aux = nod_grade.front();
            nod_grade.pop();
            lista.push(aux);
            for(int i = 1; i < lista_vecini[aux].size(); i++)
            {
                grade_interne[lista_vecini[aux][i]] --;
                if(grade_interne[lista_vecini[aux][i]] == 0)
                    nod_grade.push(lista_vecini[aux][i]);
            }
        }
        if(nr_noduri == lista.size())
            return 1;
        else
            return 0;
    }

    void Graf::DFS_biconex(int nod, int nivel_actual, vector<int> &nivel, vector<int> &nivel_minim, vector<bool> &vizitat, stack<int> &stiva, vector<vector<int>> &subgraf_biconex)
    {
        vizitat[nod] = 1;
        stiva.push(nod);
        nivel[nod] = nivel_actual;
        nivel_minim[nod] = nivel_actual;
        for(int i = 0; i < lista_vecini[nod].size(); i++)
        {
            int urm = lista_vecini[nod][i];
            if(!vizitat[urm])
            {
                DFS_biconex(urm, nivel_actual + 1, nivel, nivel_minim, vizitat, stiva, subgraf_biconex);
                nivel_minim[nod] = min(nivel_minim[nod], nivel_minim[urm]);
                if(nivel_minim[urm] >= nivel[nod])
                {
                    vector<int> subgraf;
                    int nod_subgraf;
                    do{
                        nod_subgraf = stiva.top();
                        subgraf.push_back(nod_subgraf);
                        stiva.pop();
                    }while(nod_subgraf != urm);
                    subgraf.push_back(nod);
                    subgraf_biconex.push_back(subgraf);
                }
            }
            else
            {
                nivel_minim[nod] = min(nivel_minim[nod], nivel[urm]);
            }
        }
    }

    int Graf::disjoint_gasit(int a, vector<int> &v)
    {
        int i, aux;
        for (i = a; v[i] != i; i = v[i]); // caut in arbore un nod ce pointeaza la el insusi

        for(; v[a] != a;) // realizez compresia drumurilor
        {
            aux = v[a];
            v[a] = i;
            a = aux;
        }
        return i;
    }

    void Graf::disjoint_uneste(int a, int b, vector<int> &v, vector<int> &rang)
    {
        if(rang[a] > rang[b]) // atasez multimea cu rang mai mic la cea cu rang mai mare
            v[b] = a;
        else v[a] = b;
        if(rang[a] == rang[b]) // maresc rangul multimii pe care vreau sa o adaug recent in caz de egalitate
            rang[b]++;
    }

void pb1_BFS()
{
    ifstream f("bfs.in");
    ofstream g("bfs.out");
    int N, M, S;
    f >> N >> M >> S;
    Graf graf(N, M);
    graf.graf_orientat(f);
    graf.BFS(S, g);
    f.close();
    g.close();
}

void pb2_DFS()
{
    ifstream f("dfs.in");
    ofstream g("dfs.out");
    int N, M;
    f >> N >> M;
    Graf graf(N, M);
    graf.graf_neorientat(f);
    g << graf.comp_conexe();
    f.close();
    g.close();
}

void hakimi()
{
    ifstream f("hakimi.in");
    ofstream g("hakimi.out");
    int N;
    vector<int> V(100005);
    f >> N;
    for(int i = 0; i < N; i++)
        f >> V[i];
    Graf graf(N, 0);
    graf.hakimi(N, V, g);
    f.close();
    g.close();
}

void sortaret()
{
    ifstream f("sortaret.in");
    ofstream g("sortaret.out");
    int N, M, x;
    vector<bool> viz(100005, 0);
    queue<int> lista;
    f >> N >> M;
    Graf graf(N, M);
    graf.graf_orientat_DFS(f);
    x = graf.DFS_sortaret(lista);
    if(x)
    {
        while(!lista.empty())
        {
            g << lista.front() <<" ";
            lista.pop();
        }
    }
    else
        g << "Graful nu are o sortare topologica!";
    f.close();
    g.close();
}

void biconex()
{
    ifstream f("biconex.in");
    ofstream g("biconex.out");
    int N, M;
    vector<int> nivel(100008);
    vector<int> nivel_minim(100008);
    stack<int> stiva;
    vector<bool> vizitat(100008, 0);
    vector<vector<int>> subgraf_biconex;
    f >> N >> M;
    Graf graf(N, M);
    graf.graf_neorientat(f);
    graf.DFS_biconex(1, 1, nivel, nivel_minim, vizitat, stiva, subgraf_biconex);
    g << subgraf_biconex.size() << "\n";
    for(int i = 0; i < subgraf_biconex.size(); i++)
        for(int j = 0; j < subgraf_biconex[i].size(); i++)
            g << subgraf_biconex[i][j] << " ";
    f.close();
    g.close();
}

void disjoint()
{
    ifstream f("disjoint.in");
    ofstream g("disjoint.out");
    vector<int> v(100005);
    vector<int> rang(100005);
    int cod, a, b, N, M;
    f >> N >> M;
    Graf graf(N, 0);
    for(int i = 1; i <= N; i++)
    {
        v[i] = i;
        rang[i] = 1;
    }
    for(int i = 1; i <= M; i++)
        {
            f >> cod >> a >> b;
            if (cod == 2)
            {
                if(graf.disjoint_gasit(a, v) == graf.disjoint_gasit(b, v)) //verifica daca am aceiasi radacina
                    g << "DA\n";
                else
                    g << "NU\n";
            }
            else //unesc nodurile
            {
                graf.disjoint_uneste(graf.disjoint_gasit(a, v), graf.disjoint_gasit(b, v), v, rang);
            }
        }
}

int main() {

    disjoint();
    return 0;
}