Cod sursa(job #2791000)

Utilizator DianaIfrosaIfrosa Diana DianaIfrosa Data 29 octombrie 2021 22:27:07
Problema Componente tare conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.6 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("ctc.in");
ofstream fout("ctc.out");

class graf
{
protected:
    int n;
    int m;
    const static int nmax=100001;
    vector<int> muchii[nmax]; //liste de adiacenta- array de vectori
    int dist[nmax];
    int viz[nmax];

public:
    graf(int noduri, int muchii):n(noduri), m(muchii) {}
    void BFS(int start);
    void DFS(int start, vector<int> muchii_curente[]);
    void Reseteaza_viz();
    void Reseteaza_dist();
    int Comp_conexe();
    void Afiseaza_distante();

};

class graf_orientat: public graf
{

public:
    graf_orientat(int noduri, int muchii):graf(noduri,muchii) {}
    void Citire();
    void DFStimpi(int nod, vector<int> muchii_curente[],stack<int>& timpi_final); //memoreaza si timpii de final
    void DFSctc (int nod, vector<int>  muchii_curente[], int nr_comp, vector<int> comp_tare_con[]);//memoreaza si comp tare conexe
    void CTC();
    void Graf_transpus(vector<int> muchii_transp[]);
    void SortareTopologica();

};
class graf_neorientat: public graf
{
public:
    graf_neorientat(int noduri, int muchii):graf(noduri,muchii) {}
    void Citire();

};
void graf_orientat::SortareTopologica()
{
    int grad_intern[n], vf, afisate=0;
    queue<int> sortare;

    for(int i=1; i<=n; i++)
        grad_intern[i]=0;
    //calculez gradele interne pentru noduri

    for(int i=1; i<=n; ++i)
        for(int j=0; j<muchii[i].size(); ++j)
            grad_intern[muchii[i][j]]+=1;

    //adaug toate nodurile cu grad intern 0 intr-o coada
    for(int i=1; i<=n; ++i)
        if(grad_intern[i]==0)
            sortare.push(i);


    while(!sortare.empty())
    {
        //extrag capul cozii
        vf=sortare.front();
        sortare.pop();
        fout<<vf<<" ";
        afisate++;
        for(int j=0; j<muchii[vf].size(); ++j) //scad gradele vecinilor (elimin nodul curent in mod fictiv)
        {
            grad_intern[muchii[vf][j]]--;
            if(grad_intern[muchii[vf][j]]==0)
                sortare.push(muchii[vf][j]);
        }
    }
    if(afisate!=n) //graful are cicluri
        fout<<"Nu exista sortare topologica!";

    fout<<"\n";


}
void graf_orientat::Graf_transpus(vector<int> muchii_transp[])
{
    for(int i=1; i<=n; ++i)
        for(int j=0; j<muchii[i].size(); ++j)
            muchii_transp[muchii[i][j]].push_back(i);
}
void graf_orientat::DFStimpi(int nod, vector<int> muchii_curente[],stack<int> & timpi_final)
{
    viz[nod]=1;
    for(int i=0; i<muchii_curente[nod].size(); ++i)
        if(!viz[muchii_curente[nod][i]])
            DFStimpi(muchii_curente[nod][i], muchii_curente, timpi_final);

    timpi_final.push(nod);
}
void graf_orientat::DFSctc (int nod, vector<int> muchii_curente[], int nr_comp, vector<int> comp_tare_con[])
{
    viz[nod]=1;

    comp_tare_con[nr_comp].push_back(nod);

    for(int i=0; i<muchii_curente[nod].size(); ++i)
        if(!viz[muchii_curente[nod][i]])
            DFSctc(muchii_curente[nod][i], muchii_curente, nr_comp, comp_tare_con);

}
void graf_orientat::CTC()
{
    int nr=0; //numarul de ctc
    stack<int> timpi_final;
    vector<int> muchii_transp[n+1]; //liste de adiacenta- array de vectori
    vector<int> comp_tare_con[n+1]; //ctc, poz1- elem comp1, poz2-elem comp2 et.

///crapa pentru ca am prea multe alocate local; alt alg? global? n mai mic?
    Reseteaza_viz();
    Graf_transpus(muchii_transp);

    for(int i=1; i<=n; ++i)
        if(!viz[i])
            DFStimpi(i, muchii, timpi_final);

    Reseteaza_viz();
    while(!timpi_final.empty())
    {
        int vf=timpi_final.top();
        timpi_final.pop();
        if(!viz[vf])
        {
            nr++;

            DFSctc(vf, muchii_transp, nr, comp_tare_con);
        }
    }

    fout<<nr<<"\n";
    for(int i=1; i<=nr; ++i)
    {
        for(int j=0; j<comp_tare_con[i].size(); ++j)
            fout<<comp_tare_con[i][j]<<" ";
        fout<<"\n";
    }

}
void graf::Afiseaza_distante()
{
    for(int i=1; i<=n; ++i)
        fout<<dist[i]<<" ";
    fout<<"\n";
}
int graf::Comp_conexe()
{
    Reseteaza_viz();
    int nr_comp=0;
    for(int i=1; i<=n; ++i)
        if(!viz[i])
        {
            DFS(i, muchii);
            nr_comp++;
        }

    return nr_comp;

}
void graf::Reseteaza_dist()
{
    for(int i=1; i<=n; ++i)
        dist[i]=-1;
}
void graf::Reseteaza_viz()
{
    for(int i=1; i<=n; ++i)
        viz[i]=0;
}

void graf::DFS(int nod, vector<int> muchii_curente[])
{

    viz[nod]=1;
    for(int i=0; i<muchii_curente[nod].size(); ++i)
        if(!viz[muchii_curente[nod][i]])
            DFS(muchii_curente[nod][i], muchii_curente);

}
void graf::BFS(int start)
{
    queue<int> coada;

    Reseteaza_dist();
    Reseteaza_viz();

    viz[start]=1;
    dist[start]=0;
    coada.push(start);

    while(!coada.empty())
    {
        int vf=coada.front();
        coada.pop();
        for(int i=0; i<muchii[vf].size(); ++i)
            if(!viz[muchii[vf][i]])
            {
                viz[muchii[vf][i]]=1;
                dist[muchii[vf][i]]=dist[vf]+1;
                coada.push(muchii[vf][i]);
            }

    }

}
void graf_orientat::Citire()
{
    int n1,n2;
    for(int i=0; i<m; ++i)
    {
        fin>>n1>>n2;
        muchii[n1].push_back(n2);
    }
}
void graf_neorientat::Citire()
{
    int n1,n2;
    for(int i=0; i<m; ++i)
    {
        fin>>n1>>n2;
        muchii[n1].push_back(n2);
        muchii[n2].push_back(n1);
    }
}

void HavelHakimi()
{
    vector<int> grade;
    int suma=0;
    int n,grad;

    //citire grade
    while(fin>>grad)
    {
        grade.push_back(grad);
        suma+=grad;
    }

    n=grade.size();
    //daca suma e impara sau unul din grade>n-1 nu e corect
    if(suma%2==1)
    {
        fout<<"NU\n";
        return;
    }
    for(int i=0; i<n; ++i)
        if(grade[i]>n-1)
        {
            fout<<"NU\n";
            return;
        }

    //sortez descrescator gradele
    sort(grade.begin(),grade.end(), greater<int> ());
    while(grade[0]!=0)
    {
        //decrementez cu 1 gradele de la poz 1 la grade[0]
        for(int i=1; i<=grade[0]; ++i)
        {
            grade[i]--;
            if(grade[i]<0)
            {
                fout<<"NU\n";
                return;
            }
        }
        grade[0]=0;
        sort(grade.begin(),grade.end(), greater<int> ());


    }

    fout<<"DA\n";


}

int main()
{
    int n,m;
    fin>>n>>m;
    graf_orientat g(n,m);
    g.Citire();
    g.CTC();



    return 0;
}