Pagini recente » Cod sursa (job #2354229) | Cod sursa (job #941073) | Cod sursa (job #143168) | Cod sursa (job #2917035) | Cod sursa (job #2928178)
#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[10001][10001], noduri_plus[10001], noduri_minus[10001], ctc[10001], 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;
}