Cod sursa(job #2926959)

Utilizator irinaenescu2002Enescu Irina irinaenescu2002 Data 18 octombrie 2022 23:33:25
Problema Componente tare conexe Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3 kb
#include <iostream>
#include <fstream>

using namespace std;

ifstream citeste("ctc.in");
ofstream scrie("ctc.out");


/// Vom folosi algoritmul Plus Minus:
/// -- determinam toate nodurile in care se poate ajunge din x, marcandu-le cu plus (noduri_plus)
/// -- determinam toate nodurile din care se poate ajunge din x, marcandu-le cu minus (noduri_minus)
/// Nodurile marcate cu plus si cu minus, impreuna cu nodul x vor reprezenta o componenta conexa.
/// ALgoritmul are complexitate O(n+m), iar in cazul nefavorabil O(n^2).

/// Vectorul ctc va retine numarul de ordine al componentei conexe din care face parte fiecare nod:
/// ----> ctc[i] = numarul de ordine al componentei din care face parte i

int n, m, mat[10000][10000], noduri_plus[10000], noduri_minus[10000], ctc[10000], nr_ctc;


/// Construim matricea de adiacenta a grafului (notata mat), marcand muchiile existente cu 1.

void citire()
{
    citeste >> n >> m;
    for (int i=1; i<=m; i++)
    {
        int x, y;
        citeste >> x >> y;
        mat[x][y] = 1;
    }
}


/// Folosim parcurgerea in adancime pentru a marca toate nodurile in care se poate ajunge din x.
/// Marcam nodul curent, apoi cautam muchie pentru a trece mai departe doar in cazul in care nu am
/// trecut deja prin nodul respectiv.

void dfs_plus(int nod_curent)
{
    noduri_plus[nod_curent] = 1;
    for (int i=1; i<=n; i++)
        if (mat[nod_curent][i] == 1 && noduri_plus[i] == 0)
            dfs_plus(i);
}


/// Folosim parcurgerea in adancime pentru a marca toate nodurile din care se poate ajunge din x.
/// Marcam nodul curent, apoi cautam muchie pentru a trece mai departe doar in cazul in care nu am
/// trecut deja prin nodul respectiv.

void dfs_minus(int nod_curent)
{
    noduri_minus[nod_curent] = 1;
    for (int i=1; i<=n; i++)
        if (mat[i][nod_curent] == 1 && noduri_minus[i] == 0)
            dfs_minus(i);
}


int main()
{
    /// Pentru fiecare nod incercam sa gasim componenta conexa.
    /// Daca nodul i nu apartine deja unei componenta tare-conexe, reinitializam vectorii
    /// de marcare pentru a gasi componenta sa conexa.
    /// Aplicam parcurgerile pentru a marca cu plus si minus nodurile, adaugand la numarare
    /// o noua componenta conexa.
    /// Daca un nod a fost vizitat in ambele parcurgeri, nodul respectiv face parte din componenta
    /// tare-conexa cu numarul curent.

    citire();
    for (int i=1; i<=n; i++)
        if (ctc[i] == 0)
        {
            for (int j=1; j<=n; j++)
                noduri_minus[j] = noduri_plus[j] = 0;
            nr_ctc ++;
            dfs_plus(i);
            dfs_minus(i);
             for (int j=1; j<=n; j++)
                if (noduri_minus[j] == 1 && noduri_plus[j] == 1)
                    ctc[j] = nr_ctc;
        }
    scrie << nr_ctc << '\n';
    for (int i=1; i<=nr_ctc; i++)
    {
        for (int j=1; j<=n; j++)
            if (ctc[j] == i)
                scrie << j << " ";
        scrie << '\n';
    }
    return 0;
}