Cod sursa(job #3270761)

Utilizator radiantstorkAmadeus L radiantstork Data 24 ianuarie 2025 13:12:45
Problema Componente tare conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.55 kb
#include <iostream>
#include <vector>
#include <fstream>
#include <stack>
#include <algorithm>

void citire(std::vector<std::vector<int> > &graf, std::vector<std::vector<int> > &grafTranspus, int &n) {
    std::ifstream f("ctc.in");
    int i, j;
    int m;
    f >> n >> m;
    graf.resize(n);
    grafTranspus.resize(n);
    while (m--) {
        f >> i >> j;
        graf[i - 1].push_back(j - 1);
        grafTranspus[j - 1].push_back(i - 1);
    }
    f.close();
}

void dfs(std::vector<std::vector<int> > &graf, std::vector<bool> &viz, std::stack<int> &s, const int node) {
    viz[node] = true;
    for (const auto &v: graf[node])
        if (!viz[v])
            dfs(graf, viz, s, v);
    s.push(node);
}

void kosaraju() {
    // Pasul 1: citim graful G si construim G^T.
    std::vector<std::vector<int> > graf, grafTranspus;
    int n;
    citire(graf, grafTranspus, n);

    // Pasul 2: parcurgem G cu DFS si stocam varfurile intr-o stiva.
    std::stack<int> s;
    std::vector viz(n, false);
    for (int i = 0; i < n; ++i)
        if (!viz[i])
            dfs(graf, viz, s, i);

    // Pasul 3: parcurgem G^T cu DFS. Pentru fiecare parcurgere, stocam varfurile intr-o stiva.
    std::vector<std::vector<int> > componente;
    std::fill(viz.begin(), viz.end(), false);
    while (!s.empty()) {
        const int node = s.top();
        s.pop();
        std::stack<int> aux;
        if (!viz[node])
            dfs(grafTranspus, viz, aux, node);
        if (!aux.empty()) {
            std::vector<int> componenta;
            while (!aux.empty()) {
                const int v = aux.top();
                aux.pop();
                componenta.push_back(v + 1);
            }
            componente.push_back(componenta);
        }
    }

    std::ofstream g("ctc.out");
    g << componente.size() << "\n";
    for (const auto &componenta: componente) {
        for (const auto &nod: componenta)
            g << nod << " ";
        g << "\n";
    }
    g.close();
}

int main() {
    // CERINTA: Se da un graf orientat. Sa se afiseze componentele tare conexe.

    // COMPONENTA TARE CONEXA = intre oricare 2 varfuri din componenta respectiva exista un drum.

    // Algoritmul lui Kosaraju:
    // Pasul 1: Construim graful transpus G^T (arcele sunt inversate).
    // Pasul 2: Parcurgem graful G cu DFS si introducem intr-o stiva fiecare varf la momentul la care este finalizat.
    // (vrem o ordonare descrescator a varfurilor dupa timpul de finalizare).
    // Pasul 3: Parcurgem graful G^T cu DFS considerand varfurile in ordinea in care sunt extrase din stiva.

    kosaraju();
    return 0;
}