#include <bits/stdc++.h>
#define NIL -1
using namespace std;
ifstream fin("ctc.in");
ofstream gout("ctc.out");
class Graful_meu
{
int _noduri;
int _muchii;
vector<vector<int>> lista_muchii;
public:
Graful_meu(); // daca ni se da lista de adiacenta
int Componente_conexe();
void citire_muchii_neorientat();
int citire_muchii_neorientat_cu_nod_start();
int citire_muchii_orientat_cu_nod_start();
void citire_muchii_orientat();
void DFS(int start, bool vizitat[]);
void BFS(int start);
vector <vector<int>> Componente_Biconexe(int Start);
void DFS_Componente_Biconexe(int nod_curent, stack<int>&stiva_noduri, vector<int>&low,
vector<int>&discovery_time,vector<vector<int>>&all_biconex_components);
vector<vector<int>> Componente_Tare_Conexe();
void DFS_Componente_Tare_Conexe(int nod_curent, stack<int>&stiva_noduri, vector<bool>&is_part_of_a_connected_comp, vector<int>&low,
vector<int>&discovery_time,vector<vector<int>>&all_strongly_connected_components);
};
Graful_meu::Graful_meu()
{
_noduri = 0;
_muchii = 0;
}
void Graful_meu::citire_muchii_neorientat()
{
int x, y;
fin >> _noduri;
fin >> _muchii;
lista_muchii.resize(_noduri+2);
for(int i = 1 ; i <= _muchii ; ++i)
{
fin >> x >> y;
lista_muchii[x].push_back(y);
lista_muchii[y].push_back(x);
}
}
void Graful_meu::citire_muchii_orientat()
{
int x, y;
fin >> _noduri;
fin >> _muchii;
lista_muchii.resize(_noduri+2);
for(int i = 1 ; i <= _muchii ; ++i)
{
fin >> x >> y;
lista_muchii[x].push_back(y);
}
}
int Graful_meu::citire_muchii_orientat_cu_nod_start()
{
int x, y, nod_start;
fin >> _noduri;
fin >> _muchii;
fin >> nod_start;
lista_muchii.resize(_noduri+2);
for(int i = 1 ; i <= _muchii ; ++i)
{
fin >> x >> y;
lista_muchii[x].push_back(y);
}
return nod_start;
}
int Graful_meu::citire_muchii_neorientat_cu_nod_start()
{
int x, y, nod_start;
fin >> _noduri;
fin >> _muchii;
fin >> nod_start;
lista_muchii.resize(_noduri+2);
for(int i = 1 ; i <= _muchii ; ++i)
{
fin >> x >> y;
lista_muchii[x].push_back(y);
lista_muchii[y].push_back(x);
}
return nod_start;
}
void Graful_meu::DFS(int start, bool vizitat[])
{
vizitat[start] = 1;
for(int nod_vecin : lista_muchii[start])
if(vizitat[nod_vecin] == 0)
DFS(nod_vecin, vizitat);
}
int Graful_meu::Componente_conexe()
{
bool vizitat[_noduri + 2] = {0};
int numar_componente_conexe = 0;
for(int i = 1 ; i <= _noduri ; ++i)
if (vizitat[i] == 0)
{
DFS(i, vizitat);
++numar_componente_conexe;
}
return numar_componente_conexe;
}
void Graful_meu::BFS(int start)
{
bool vizitat[_noduri + 2] = {0};
queue<int>coada_BFS;
vector<int> drumuri_minime(_noduri + 2, -1);
coada_BFS.push(start);
vizitat[start] = 1;
drumuri_minime[start] = 0;
while(!coada_BFS.empty())
{
for(int nod_vecin : lista_muchii[start])
if(vizitat[nod_vecin] == 0)
{
coada_BFS.push(nod_vecin);
vizitat[nod_vecin] = 1;
drumuri_minime[nod_vecin] = drumuri_minime[start] + 1;
}
coada_BFS.pop();
start = coada_BFS.front();
}
for(int i = 1 ; i <= _noduri ; ++i)
gout << drumuri_minime[i] << " ";
}
vector<vector<int>> Graful_meu::Componente_Biconexe(int Start)
{
vector<int>discovery_time(_noduri + 2, NIL);
vector<int>low(_noduri + 2, NIL);
vector<vector<int>> all_biconex_components;
stack<int>stiva_noduri;
DFS_Componente_Biconexe(Start, stiva_noduri, low, discovery_time, all_biconex_components);
return all_biconex_components;
}
void Graful_meu::DFS_Componente_Biconexe(int nod_curent, stack<int>&stiva_noduri, vector<int>&low,
vector<int>&discovery_time,vector<vector<int>>&all_biconex_components)
{
static int time = 0;
low[nod_curent] = discovery_time[nod_curent] = ++time;
stiva_noduri.push(nod_curent);
for(auto vecin : lista_muchii[nod_curent])
{
if(discovery_time[vecin] == NIL)
{
DFS_Componente_Biconexe(vecin, stiva_noduri, low, discovery_time, all_biconex_components);
low[nod_curent] = min(low[nod_curent], low[vecin]);
if(low[vecin] >= discovery_time[nod_curent])
{
vector<int>one_biconex_component;
int nod_stiva = stiva_noduri.top();
stiva_noduri.pop();
one_biconex_component.push_back(nod_stiva);
while(nod_stiva != vecin)
{
nod_stiva = stiva_noduri.top();
stiva_noduri.pop();
one_biconex_component.push_back(nod_stiva);
}
one_biconex_component.push_back(nod_curent);
all_biconex_components.push_back(one_biconex_component);
}
}
else
low[nod_curent] = min(low[nod_curent], discovery_time[vecin]);
}
}
vector<vector<int>> Graful_meu::Componente_Tare_Conexe()
{
vector<int>discovery_time(_noduri + 2, NIL);
vector<int>low(_noduri + 2, NIL);
vector<vector<int>> all_strongly_connected_components;
stack<int>stiva_noduri;
vector<bool>is_part_of_a_connected_comp(_noduri + 2, false);
for(int i = 1 ; i <= _noduri ; ++i)
if(discovery_time[i] == NIL)
DFS_Componente_Tare_Conexe(i, stiva_noduri, is_part_of_a_connected_comp, low, discovery_time, all_strongly_connected_components);
return all_strongly_connected_components;
}
void Graful_meu::DFS_Componente_Tare_Conexe(int nod_curent, stack<int>&stiva_noduri, vector<bool>&is_part_of_a_connected_comp, vector<int>&low,
vector<int>&discovery_time,vector<vector<int>>&all_stongly_connected_components)
{
static int time = 0;
low[nod_curent] = discovery_time[nod_curent] = ++time;
stiva_noduri.push(nod_curent);
for(auto vecin : lista_muchii[nod_curent])
{
if(discovery_time[vecin] == NIL)
{
DFS_Componente_Tare_Conexe(vecin, stiva_noduri, is_part_of_a_connected_comp, low, discovery_time, all_stongly_connected_components);
low[nod_curent] = min(low[nod_curent], low[vecin]);
}
else
if(is_part_of_a_connected_comp[vecin] == false)
low[nod_curent] = min(low[nod_curent], discovery_time[vecin]);
}
if(low[nod_curent] == discovery_time[nod_curent])
{
vector<int>one_strongly_connected_component;
int nod_stiva = stiva_noduri.top();
while(nod_stiva != nod_curent)
{
one_strongly_connected_component.push_back(nod_stiva);
is_part_of_a_connected_comp[nod_stiva] = true;
stiva_noduri.pop();
nod_stiva = stiva_noduri.top();
}
one_strongly_connected_component.push_back(nod_stiva);
is_part_of_a_connected_comp[nod_stiva] = true;
stiva_noduri.pop();
all_stongly_connected_components.push_back(one_strongly_connected_component);
}
}
int main()
{
Graful_meu g;
// DFS - Componente conexe
/*
g.citire_muchii_neorientat();
gout << g.Componente_conexe();
*/
// BFS
/*
int nod_start = g.citire_muchii_orientat_cu_nod_start();
g.BFS(nod_start);
*/
// Componente biconexe - Algoritm Tarjan modificat
/*
g.citire_muchii_neorientat();
vector<vector<int>>toate_componentele_biconexe = g.Componente_Biconexe(1);
gout << toate_componentele_biconexe.size() << '\n';
for(auto &one_biconex_comp : toate_componentele_biconexe)
{
for(auto element : one_biconex_comp)
gout << element << " ";
gout << '\n';
}
*/
// Componente tare conexe - Algoritm Tarjan
g.citire_muchii_orientat();
vector<vector<int>>toate_componentele_tare_conexe = g.Componente_Tare_Conexe();
gout << toate_componentele_tare_conexe.size() << '\n';
for(auto &one_strongly_connected_comp : toate_componentele_tare_conexe)
{
for(auto element : one_strongly_connected_comp)
gout << element << " ";
gout << '\n';
}
return 0;
}