Cod sursa(job #2926076)

Utilizator andlftLefter Andrei andlft Data 16 octombrie 2022 21:11:43
Problema Componente tare conexe Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.97 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <set>
#include <unordered_map>
 
//complexitate timp O(n+m)
//complexitate spatiu O(n+m)
 
using namespace std;
 
ifstream fin("ctc.in");
ofstream fout("ctc.out");
int n, m;
 
 
vector <int> arce[100005]; //<-voi retine graful asa cum este dat de problema
vector <int> redenumiri;   //<-fiecare nod va primi un nou numar, care va fi tinut in redenumiri
vector <int> nod_min;      //<-se va retine valoarea minima pe care o are un vecin al nodului din aceeasi ctc
vector <bool> pe_stiva;    //<-se va marca daca nodul este pe stiva
stack <int> stiva;         //<-stiva unde se tin nodurile care ar putea fi in aceeasi ctc cu nodul curent
int id_nou;                //<-iterator pentru redenumirea nodurilor
set <int> minime;           //<-multime in care tin valorile minime ale nodurilor
unordered_map <int, vector<int>> ctc; //<- tine pentru fiecare valoare minima nodurile care au acea valoare minima
 
 
 
 
void dfs(int nod)
{
//    cout<<"nod: "<<nod<<endl;
    redenumiri[nod] = id_nou;       //sa da un nou id-nodului
    nod_min[nod] = id_nou;          //minimul acelui nod este initial chiar el insusi
    id_nou++;
    stiva.push(nod);              //se pune nodul pe stiva
    pe_stiva[nod] = true;            //se marcheaza nodul ca fiind pe stiva
 
    for (int i = 0; i<arce[nod].size(); i++)  //pentru fiecare vecin al nodului curent
    {
        if(redenumiri[arce[nod][i]]== -1)     //daca nodul adiacent nu este vizitat se face dfs pe el
        {
            dfs(arce[nod][i]);
        }
        if (pe_stiva[arce[nod][i]])         //daca nodul vecin este pe stiva, val min a nodului curent
        {                                   // devine minimul dintre val min ale celor doua noduri
            nod_min[nod] = min(nod_min[nod], nod_min[arce[nod][i]]);
        }
    }
 
    if (redenumiri[nod] == nod_min[nod])  //daca val_min este egala cu redenumirea, inseamna ca s-a parcurs o ctc
    {
        while(true)
        {
            int top = stiva.top();      //se scot toate elementele de pe stiva pana la nodul curent inclusiv
            pe_stiva[top] = false;      // se marcheaza nodurile scoase de pe stiva
            nod_min[top] = redenumiri[nod];  //toate elementele unei ctc trebuie sa aiba acelasi val min
            stiva.pop();
            if(top == nod)
            {
                break;
            }
        }
    }
 
}
 
int main()
{
    fin>>n>>m;
 
    id_nou = 1;
 
 
    for(int i = 0; i <= n; i++)
    {
        redenumiri.push_back(-1);  //"initializez" vectorii
        nod_min.push_back(-1);
        pe_stiva.push_back(false);
    }
 
    for(int i=0; i<m; i++)
    {
        int p1, p2;     //fac lista de adiacenta
        fin>>p1>>p2;
        arce[p1].push_back(p2);
    }
 
 
    for(int i=1; i<n+1; i++)   //ma asigur ca se face dfs pe toate nodurile
                               // chiar daca graful are mai multe elemente conexe
    {
        if(redenumiri[i] == -1)
        {
            dfs(i);
        }
    }
 
    for(int i = 1; i < nod_min.size(); i++)
    {
        //cout<<nod_min[i]<<" ";
        minime.insert(nod_min[i]);   //fac o multime cu valorile minime ale nodurilor
    }
    //cout<<endl;
    fout<<minime.size();
    fout<<endl;
 
    for(auto it = minime.begin(); it != minime.end(); it++)
 
    {
        vector<int> vec;
        ctc.insert(pair<int, vector<int>>(*it, vec));  //pun empty vectors in map pt val min
    }
 
    for(int i = 1; i < nod_min.size(); i++)
    {
        ctc[nod_min[i]].push_back(i);  //inserez nodurile pentru fiecare valoare minima
    }
 
    for(auto it = ctc.begin(); it != ctc.end(); it++)
    {
        for(auto it2 = it->second.begin(); it2 != it->second.end(); it2++)
        {
            fout<<*it2<<" ";   //afisez pt fiecare val min nodurile corespunzatoare, adica ctc-urile
        }
        fout<<endl;
    }
 
    return 0;
}