Cod sursa(job #2796607)

Utilizator amalia.gemanGeman Aamalia amalia.geman Data 8 noiembrie 2021 15:43:29
Problema Componente biconexe Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 8.11 kb
#include <bits/stdc++.h>

#define NMax 100001

using namespace std;

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


// DFS
bool vizDFS[NMax];

// Kosaraju
stack <int> S; // stiva pentru memorarea nodurilor in ordinea timpilor de final
bool vizDFST[NMax]; // pt graful transpus
vector <int> grT[NMax]; // liste de adiacenta ale grafului transpus
vector <int> componente[NMax]; // liste cu nodurile care compun fiecare componenta tare conexa in parte

// Havel-Hakimi
vector <int> grade;

// Muchii Critice + Comp Biconexe
bool vizDFSC[NMax];
int nivel[NMax]; // nivelul pe care se gaseste nodul
int niv_min_acc[NMax]; // nivelul minim accesibil
int ct_muchii_critice;
vector <vector<int>> muchii_critice;

// Biconex
int ct_biconexe;
stack <int> S2;
vector <int> componente_biconexe[NMax];


class graf
{
    int nrNoduri, nrMuchii;
    bool orientat;
    vector <int> gr[NMax]; // liste de adiacenta ale grafului

public:
    graf(int n, int m, bool o); // constructor
    void Citire_Orientat();
    void Citire_Neorientat();
    void Afisare_Graf();

    void BFS(int s); // s - nodul de start
    void DFS(int s); // s - nodul de start

    // Determinare nr de componente conexe
    void Comp_Conexe(); // afiseaza cate componente conexe are graful

    // Kosaraju
    void Graf_Transpus(); // creeaza graful transpus in grT
    void ParcurgereGrafInitial(); // parcurgerea in adancime a grafului initial
    void DFST(int s, int culoare); // s - nodul de start, dfs pe graful transpus
    void CTC(); // apeleasa DFST si afiseaza comp tare conexe

    // Sortare topologica
    void Sortare_Topologica();

    // Algoritm Havel-Hakimi
    bool Havel_Hakimi(vector<int>grade, int nrNoduri);

    // Afisare Muchii Critice
    void Muchii_Critice();
    void DFS_Critice(int s, int tata);

    // Afisare Componente Biconexe
    void DFS_Biconex(int s, int tata);
    void Componente_Biconexe();
};



graf :: graf(int n, int m, bool o)
{
    nrNoduri = n;
    nrMuchii = m;
    orientat = o;
}

void graf :: Citire_Orientat()
{
    for(int i = 1; i <= nrMuchii; ++i)
    {
        int x, y;
        fin >> x >> y;
        gr[x].push_back(y);
    }
}

void graf :: Citire_Neorientat()
{
    for(int i = 1; i <= nrMuchii; ++i)
    {
        int x, y;
        fin >> x >> y;
        gr[x].push_back(y);
        gr[y].push_back(x);
    }
}

void graf :: Graf_Transpus()
{
    for(int i = 1; i <= nrNoduri; ++i)
        for(auto j : gr[i])
            grT[j].push_back(i);
}

void graf :: Afisare_Graf()
{
    for(int i=1; i <= nrNoduri; ++i)
    {
        fout << i << " : " ;
        for(auto j: gr[i])
            fout << j << " ";
        fout << "\n";
    }
}

void graf :: BFS(int s)
{
    bool viz[NMax] = {0};
    int distanta[NMax] = {0};
    queue <int> q;

    viz[s] = 1;
    q.push(s);

    while(!q.empty())
    {
        int k = q.front();  // elem din varful cozii
        q.pop();            // sterg elem din varful cozii
        for(auto i : gr[k])
            if(!viz[i])
            {
                viz[i] = 1;
                q.push(i);
                distanta[i] = distanta[k] + 1;
            }
    }

    for(int i = 1; i <= nrNoduri; ++i)
        if(viz[i])
            fout << distanta[i] << " ";
        else
            fout << -1 << " ";
}

void graf :: DFS(int s)
{
    vizDFS[s] = 1;
    for(auto i : gr[s])
        if(!vizDFS[i])
            DFS(i);

    // pentru CTC(Kosaraju) - stabilim timpul de finalizare pentru nodul s
    S.push(s);
}

void graf :: Comp_Conexe()
{
    int ct = 0;
    for(int i = 1; i <= nrNoduri; ++i)
        if(!vizDFS[i])
        {
            ct++;
            DFS(i);
        }
    fout << ct;
}

void graf :: ParcurgereGrafInitial()
{
    for(int i = 1; i <= nrNoduri; ++i)
        if(!vizDFS[i])
            DFS(i);
}

void graf :: DFST(int s, int ct)
{
    vizDFST[s] = 1;
    componente[ct].push_back(s);
    for(auto i : grT[s])
        if(!vizDFST[i])
            DFST(i, ct);
}

void graf :: CTC()
{
    int ct_ctc = 0;
    while(!S.empty())
    {
        int varf = S.top();
        S.pop();
        if(!vizDFST[varf])
        {
            ct_ctc ++;
            DFST(varf, ct_ctc);
        }
    }

    fout << ct_ctc << "\n";

    for(int i = 1; i <= ct_ctc; ++i)
    {
        for(auto j:componente[i])
            fout << j << " ";
        fout << "\n";
    }
}

void graf :: Sortare_Topologica()
{
    ParcurgereGrafInitial();
    while(!S.empty())
    {
        fout << S.top() << " ";
        S.pop();
    }
}

bool myfunction(int i, int j)
{
    return (i>j);
}

bool graf :: Havel_Hakimi(vector <int> grade, int nrNoduri)
{
    bool ok =1;
    while(ok)
    {
        sort(grade.begin(), grade.end(), myfunction);

        if(grade[0] == 0) // daca cel mai mare element dupa sortare este 0 => toate elementele sunt 0 => se poate forma
            return true;

        if(grade[0] > grade.size() - 1) // daca gradul este mai mare decat nr de noduri curente - 1 => NU se poate forma
            return false;

        int grad_curent = grade[0];
        grade.erase(grade.begin() + 0); // elimin primul element

        for(int i = 0; i < grad_curent; ++i) // scad 1 doar din primele grad_curent elemente
        {
            grade[i] --;
            if(grade[i] < 0)
                return false;
        }
    }
}

void graf :: DFS_Critice(int s, int tata)
{
    vizDFSC[s] = 1;
    nivel[s] = nivel[tata] + 1;
    niv_min_acc[s] = nivel[s];

    for(auto i : gr[s])
        if(i != tata)
        {
            if(vizDFSC[i] == 1)
            {
                if(niv_min_acc[s] > nivel[i])
                    niv_min_acc[s] = nivel[i];
            }
            else
            {
                DFS_Critice(i,s);
                if(niv_min_acc[s] > niv_min_acc[i])
                    niv_min_acc[s] = niv_min_acc[i];
            }

            // determinare muchii critice
            if(nivel[s] < niv_min_acc[i])
            {
                // (s, i)
                ct_muchii_critice++;
                vector <int> v1;
                v1.push_back(s);
                v1.push_back(i);
                muchii_critice.push_back(v1);
            }
        }
}

void graf :: Muchii_Critice()
{
    DFS_Critice(1,0);

    fout << ct_muchii_critice << "\n";

    for( vector<vector<int>>::iterator i = muchii_critice.begin() ; i != muchii_critice.end(); i++ )
    {
        fout << "[" ;
        vector<int>::iterator j = i->begin();
        fout<<*j;
        fout << ",";
        j++;
        fout <<*j;
        fout << "] ";
    }
}

void graf :: DFS_Biconex(int s, int tata)
{
    vizDFSC[s] = 1;
    S2.push(s);

    nivel[s] = nivel[tata] + 1;
    niv_min_acc[s] = nivel[s];

    for (auto i : gr[s])
    {
        if (vizDFSC[i] == 1)
        {
            if(niv_min_acc[s] > nivel[i])
                niv_min_acc[s] = nivel[i];
        }
        else
        {
            DFS_Biconex(i, s);

            if(niv_min_acc[s] > niv_min_acc[i])
                niv_min_acc[s] = niv_min_acc[i];


            // determinare componente biconexe
            if(niv_min_acc[i] >= nivel[s])
            {
                ct_biconexe ++;

/*
                while(!S2.empty() && S2.top() != i)
                {
                    componente_biconexe[ct_biconexe].push_back(S2.top());
                    S2.pop();
                }
                componente_biconexe[ct_biconexe].push_back(S2.top());
                S2.pop();
                componente_biconexe[ct_biconexe].push_back(s);
*/
            }
        }
    }
}

void graf :: Componente_Biconexe()
{
    DFS_Biconex(1,0);


    fout << ct_biconexe << "\n";
/*
    for(int i = 1; i <= ct_biconexe; ++i)
    {
        for(auto j : componente_biconexe[i])
            fout << j << " ";
        fout << "\n";
    }
*/
}




int N, M;

int main()
{
    fin >> N >> M;
    graf G(N, M, 0);
    G.Citire_Neorientat();
    G.Componente_Biconexe();

    return 0;
}