Cod sursa(job #2822258)

Utilizator oana_mireaMirea Oana-Gabriela oana_mirea Data 23 decembrie 2021 19:12:14
Problema Parcurgere DFS - componente conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 12.34 kb
#include <bits/stdc++.h>
#include <iostream>
#include <fstream>


using namespace std;
vector<vector<int> >lista_ad_2;
ifstream fin("dfs.in");
ofstream gout("dfs.out");

class Graf{
private:
    bool orientat;
    int noduri;
    vector< vector<int> > lista_ad;
    vector< vector<int> > matrice;

    vector< pair< pair <int, int>, int> > lista_muchii;
    vector< vector<pair<int, int> > > lista_adiac;
    priority_queue <pair<int, int>, vector <pair<int,int> >, greater <pair<int,int> > > coada;
    vector<int> Dist;
    vector< int > reprez;
    vector< int > dim;
    vector< pair<int, int> > rez;
    int muchii = 0;
public:
    Graf ();
    Graf (int noduri,bool o);
    void citire_graf(int m, bool o);
    void BFS(int start);
    void DFSfaraDist(int start, vector<bool>& parcurs);
    void DFS(int start, vector<bool>& p, vector<int>& dist, int d);
    int Conexe(int n, int s);
    void DFSsort(int s, vector<int>& p, stack<int>& st);
    void SortTopologica(int n);
    void DFSt(int s, vector<int>& p,vector<vector<int> >&s2, int ctc);
    void CTC();
    pair<int,int> DistMax(vector<int> d);
    void diam();
    void citire_graf_Floyd();
    void Floyd();

     void citire_graf2(int m);
    void APM();
    void unite(int x, int y);
    int Find(int x);
    void Disjoint(int x, int y, int op);
    void unite_disjoint(int n1, int n2);
    void initializare_vectori(int m);
    void citire_Bellman(int m);
    void Dijkstra();
    void Bellman_Ford();
};
Graf :: Graf ()
{
    orientat = 1;
    vector < vector<int> > aux;
    noduri = 0;
    lista_ad =  aux;

}

Graf :: Graf (int n, bool orr)
{   orientat = orr;
    noduri = n;
    lista_ad.resize(noduri + 1);
}
void Graf :: citire_graf (int muchii, bool orientat)
{
    int x,y;
    for ( int i = 1; i <= muchii; i++ )
    {
        fin >> x >> y;
        lista_ad[x].push_back(y);
        if (orientat == 0)
            lista_ad[y].push_back(x);
}
}

void Graf :: BFS(int start)
{
    vector <int> dist(noduri+1, -1);
    vector <bool> parcurs(noduri+1, 0);
    queue <int> q;


    dist[start] = 0;
    q.push(start);
    parcurs[start] = 1;

    while (!q.empty())
    {
        for (int j = 0; j < lista_ad[q.front()].size();j++)
        {
            int vecin = lista_ad[q.front()][j];
            if (parcurs[vecin] == 0)
            {
                q.push(vecin);
                parcurs [vecin] = 1;
                dist[vecin] = dist [q.front()] + 1;

            }
        }
        q.pop();}
        for (int i = 1; i <= dist.size()-1;i++)
        {
            gout<< dist[i]<<' ';
        }

    }
void Graf :: DFSfaraDist(int start, vector<bool>& parcurs)
{
    parcurs [start] = 1;
    for (int i = 0; i < lista_ad[start].size(); i++)
    {
        if (parcurs[lista_ad[start][i]] == 0 )
            {
                DFSfaraDist(lista_ad[start][i],parcurs);
            }

    }
}

void Graf :: DFS(int start, vector<bool>& parcurs, vector<int>& dist, int d)
{
    dist[start] = d;
    parcurs [start] = 1;
    for (int i = 0; i < lista_ad[start].size(); i++)
    {
        if (parcurs[lista_ad[start][i]] == 0 )
            {
                DFS(lista_ad[start][i],parcurs,dist, d+ 1);
            }

    }
}

void Graf ::DFSsort(int start, vector<int>& parcurs, stack<int>& s)
{
    parcurs [start] = 1;
    for (int i = 0; i < lista_ad[start].size(); i++)
    {
        if (parcurs[lista_ad[start][i]] == 0 )
                Graf::DFSsort(lista_ad[start][i],parcurs,s);
    }
s.push(start);
}

int Graf:: Conexe(int noduri, int start)
{
    vector <bool> parcurs1(noduri+1,0);
    int CompConexe = 0;

for(int i = 1; i<=noduri; i++)
{
    if(parcurs1[i] == 0)
        {   CompConexe++;
            Graf::DFSfaraDist(i, parcurs1);
}}
return CompConexe;
}


void Graf:: SortTopologica(int noduri)
{
    stack <int> s;
    vector<int> parcurs(noduri+1, 0);
    for(int i = 1; i<=noduri; i++)
{
    if(parcurs[i] == 0)
        Graf::DFSsort(i, parcurs, s);
}

while(s.empty()==0)
    {
    gout<<s.top()<<' ';
	s.pop();
	}
}

void Graf :: DFSt(int start, vector<int>& parcurs,vector<vector<int> >& s2, int ctc)
{
    parcurs[start] = 2;
    s2[ctc].push_back(start);
        for(int i = 0; i < lista_ad_2[start].size(); i++){
        if(parcurs[lista_ad_2[start][i]] == 1)
            Graf::DFSt(lista_ad_2[start][i], parcurs,s2, ctc);
    }
    }

void Graf::CTC()
{   int ctc = 0;
    stack <int> s;
    vector<int> parcurs(noduri+1, 0);
    vector<vector<int> > s2;
    s2.resize(noduri+1);
    for(int i = 1; i<= noduri; i++)
        if(parcurs[i] == 0)
            Graf::DFSsort(i, parcurs, s);

    while (s.empty() == 0)
    {
        int x = s.top();
        if(parcurs[x] == 1)
        {
            ctc++;
            Graf::DFSt(x,parcurs,s2,ctc);

        }
        s.pop();
    }


    gout<<ctc;
        for (int i = 0; i < s2.size(); i++)
    {gout<<'\n';
       if (s2[i].size() != 0)
        {
           for (int j = 0; j < s2[i].size(); j++)
              gout << s2[i][j] << ' ';
        }
    }
}



void SortareDescrescator(vector <int>& a)
{
    sort(a.begin(), a.end(), greater<int>());
}

int HavelRez(vector<int> sir_grade)
{
while(sir_grade[0] != 0 )
    {
    int fst = sir_grade[0];
    sir_grade.erase(sir_grade.begin());
    if (fst > sir_grade.size())
        return 0;
    for(int i = 0; i < fst; i++)
            {sir_grade[i]--;
            if(sir_grade[i] == -1)
                return 0;
            }
        SortareDescrescator(sir_grade);
    }

return 1;
}

void Havel()
{int n,x;
    cin>>n;
    vector <int> sir_grade;
    for(int i = 0; i < n; i++)
    {
        cin>>x;
        sir_grade.push_back(x);
    }
     SortareDescrescator(sir_grade);
    if (HavelRez(sir_grade) == 1)
        cout<<"Da, se poate forma un graf";
    else cout<<"Nu se poate forma un graf";
}


void Graf :: citire_graf2 (int muchii)
{
    int x,y,c;
    for ( int i = 1; i <= muchii; i++ )
    {
        cin >> x >> y >>c;
        lista_muchii.push_back(make_pair(make_pair(x,y),c));
    }
}
int Graf :: Find(int x) {
    if(x == reprez[x])
        return x;
    return Find(reprez[x]);

}


bool SorteazaDupaCost(const pair< pair<int,int>, int> &a,
                    const pair< pair<int,int>, int> &b)
{
    return (a.second < b.second);
}

void Graf:: unite(int nod1,int nod2)
{
    int x = Graf::Find(nod1);
    int y = Graf::Find(nod2);

    if (dim[x] >= dim[y])
    {
    reprez[y] = x;
    dim[x] += dim[y];
    muchii++;
    }
    else
    {
        reprez[x] = y;
        dim[y] += dim[x];
        muchii++;
    }

}

void Graf:: unite_disjoint(int nod1,int nod2)
{
    int x = Graf::Find(nod1);
    int y = Graf::Find(nod2);

    if (dim[x] >= dim[y])
    {
    reprez[y] = x;
    dim[x] += dim[y];
    muchii++;
    }
    else
    {
        reprez[x] = y;
        dim[y] += dim[x];
        muchii++;
    }

}

void Graf :: APM()
{   int suma_cost = 0;
    muchii = 0;
    reprez.resize(noduri+1);
    dim.resize(noduri+1);
    for(int i = 1; i <= noduri; i++)
        {reprez[i] = i;
        dim[i] = 1;
        }
    sort(lista_muchii.begin(), lista_muchii.end(),SorteazaDupaCost);
    for (int i = 0; i < lista_muchii.size(); i++)
        {   int x = lista_muchii[i].first.first;
            int y =  lista_muchii[i].first.second;
            if(Find(x) != Find(y))
           {
               rez.push_back(make_pair(y, x));
               unite(y,x);
            suma_cost+= lista_muchii[i].second;
           }}
    gout<<suma_cost<<'\n';
    gout<<muchii<<'\n';
    for(int i = 0; i< muchii; i++)
        gout<<rez[i].first << ' ' << rez[i].second<<'\n';

}

void Graf::initializare_vectori(int n)
{
    reprez.resize(noduri+1);
    dim.resize(noduri+1);
    for(int i = 1; i <= n; i++)
        {reprez[i] = i;
        dim[i] = 1;
        }
}
void Graf:: Disjoint(int x, int y, int op)
{
        if(op == 1)
            unite(x,y);
        else
            {if(Find(x) == Find(y))
                gout<<"DA"<<'\n';
            else gout<<"NU"<<'\n';
                }
        }

void Graf::citire_Bellman(int muchii)
{
     int x,y,c;
    for ( int i = 1; i <= muchii; i++ )
    {
        fin >> x >> y >>c;
        lista_adiac[x].push_back(make_pair(y,c));
    }
}

void Graf::Dijkstra()
{
    vector<bool> parcurs;
    parcurs.resize(noduri+1);
    coada.push(make_pair(0,1));
    Dist.resize(noduri+1);
    for(int i = 1; i<= noduri;i++)
    {
        Dist[i] = 10000000;
        parcurs[i] = 0;
    }
    Dist[1] = 0;
    while (!coada.empty())
    {
        int curr = coada.top().second;
        if(parcurs[curr] == 1)
            continue;
         parcurs[curr] = 1;
         coada.pop();


        for(int i = 0; i < lista_adiac[curr].size();i++)
            {
                if(Dist[curr] + lista_adiac[curr][i].second < Dist[lista_adiac[curr][i].first])
                {

                    Dist[lista_adiac[curr][i].first]=Dist[curr]+lista_adiac[curr][i].second;
                    coada.push(make_pair(Dist[lista_adiac[curr][i].first],  lista_adiac[curr][i].first));
                }
            }
    }
    for(int i = 2; i <= noduri; i++)
        if (Dist[i] == 10000000)
            gout<<0<<' ';
        else
            gout<<Dist[i]<<' ';

}


void Graf::Bellman_Ford()
{
    bool ok = 1;
    vector<bool> in_coada;
    vector<int> dist;
    vector<int> iteratii;
    queue<int> coada;
    iteratii.resize(noduri+1);
    dist.resize(noduri+1);
    in_coada.resize(noduri+1);
 for(int i = 1; i<= noduri;i++)
    {
        dist[i] = 1000000;
        iteratii[i] = 0;
    }
in_coada[1] = 1;
dist[1] = 0;
coada.push(1);
while (!coada.empty())
    {
        int curr = coada.front();
        in_coada[curr]=0;
        iteratii[curr]++;
         coada.pop();
        if(iteratii[curr] > noduri)
        {
            gout<<"Ciclu negativ!";
            ok = 0;
            break;
        }

        for(int i = 0; i < lista_adiac[curr].size();i++)
            {
                if(dist[curr] + lista_adiac[curr][i].second < dist[lista_adiac[curr][i].first])
                {
                    dist[lista_adiac[curr][i].first]=dist[curr]+lista_adiac[curr][i].second;
                    if(!in_coada[curr])
                    {
                        coada.push(lista_adiac[curr][i].first);
                        in_coada[lista_adiac[curr][i].first] = 1;
                    }
                }
            }
    }
    if (ok == 1)
        for(int i = 2; i <= noduri; i++)
            gout<<dist[i]<<' ';

}

pair<int,int> Graf::DistMax(vector<int> dist) {

    int maxim = 0, nod = 0;
    for(int i=1;i<=noduri;++i) {
        if (dist[i] > maxim) {
    maxim = dist[i];
    nod = i;
}
}
}

void Graf:: diam()
{
    int x;
    vector <bool> parcurs(noduri+1,0);
    vector <int> dist(noduri+1, 0);
    Graf::DFS(1, parcurs, dist, 0);
    pair<int,int> nod1 = DistMax(dist);
    for(int i=1; i<=noduri; i++)
    {
        parcurs[i] = 0;
        dist[i] = 0;
    }
    Graf::DFS(nod1.second, parcurs, dist, x);
    pair<int,int> nod2 = DistMax(dist);
    gout << nod2.first + 1 << '\n';

}

void Graf :: citire_graf_Floyd()
{

    int x;
    matrice.resize(noduri+1);
    for ( int i = 0; i < noduri; i++ )
    {
        matrice[i].resize(noduri+1);
        for (int j = 0; j< noduri; j++)
        {
            fin>>x;
            matrice[i][j] = x;
        }
    }
}
void Graf::Floyd()
{
    vector< vector<int> > dist = matrice;

     for (int i = 0; i <  noduri; i++)
        for (int j = 0; j < noduri; j++)
            if(matrice[i][j]==0 && i != j)
                dist[i][j] = 100000;

     for (int k = 0; k < noduri; k++)
        for (int i = 0; i < noduri; i++)
             for (int j = 0; j < noduri; j++)
                 if (dist[i][j] > dist[k][j] + dist[i][k] && i!=j)
                                dist[i][j] =   dist[k][j] + dist[i][k];
 for(int i = 0; i < noduri; i++)
    {
        for (int j = 0; j < noduri; j++)
            gout << dist[i][j] << " ";
        gout << '\n';
    }
}
int main()
{
    int n,m;
    fin>>n>>m;
    Graf g(n,0);
    g.citire_graf(m,0);
    gout<<g.Conexe(n,1);
    return 0;
}