Pagini recente » Cod sursa (job #2311928) | Cod sursa (job #936071) | Cod sursa (job #1605354) | Cod sursa (job #1562251) | Cod sursa (job #2798610)
#include <bits/stdc++.h>
#define Nmax 100001
using namespace std;
ifstream fin("ctc.in");
ofstream fout("ctc.out");
// aici folosesc 2 vectori de noduri vizitate, unul pt graful normal, unul pt graful transpus (in ideea alg. plus minus)
int n, m, nrCTC, visited1[Nmax], visited2[Nmax], compCurenta, comp[Nmax];
vector<int> la[Nmax], grafTranspus[Nmax], sol[Nmax], S; // folosim graful transpus doarece ne intereseaza sa putem ajunge din orice nod
// al componentei conexe in oricare altul tot al sau => verificam asa accesibilitatea
void dfsG(int x)
{
visited1[x] = 1;
for (int i = 0; i < la[x].size(); ++i)
if (visited1[la[x][i]] == 0) { // marcam in viz1 nodurile vizitate de dfs aplicat pe graful normal (in semn de plus)
//cout << "->dfsG(" << la[x][i] << ")\n";
dfsG(la[x][i]);
//cout << "Back to " << x << endl;
}
//cout << "Push " << x << endl;
S.push_back(x); // ca sa pastreze ordinea de finalizare a nodurilor => parcurg GT in ordinea in care le scot de pe stiva
}
void dfsGT(int x) // aplicam dfs si pe graful transpus
{
//cout << "sol[" << nrCTC << "].push_back( " << x << ");\n";
sol[compCurenta].push_back(x);
comp[x] = compCurenta;
//cout << "comp["<< x <<"] = " << compCurenta << endl;
visited2[x] = 1;
for (int i = 0; i < grafTranspus[x].size(); i++)
if (visited2[grafTranspus[x][i]] == 0) // daca sunt marcate inseamna ca nu fac parte din aceasta CTC sau le-am viz deja pt CTC curenta
{
//cout << "->dfsGT(" << grafTranspus[x][i] << ")\n";
dfsGT(grafTranspus[x][i]);
//cout << "Back to " << x << endl;
}
}
/*
void Kosaraju()
{
for (int i=1; i<=n; i++)
if (!visited1[i]) {
//cout << "->dfsG(" << i << ")\n";
dfsG(i);
}
reverse(S.begin(), S.end());
for (int i=1; i<=n; i++) {
auto x = S[i];
if (!comp[x]) {
//cout << "->dfsG(" << i << ")\n";
compCurenta ++;
dfsGT(x);
}
}
// cout << "Stiva:\n";
// for (int i = S.size()-1; i>=0; i--) {
// if (!visited2[S[i]]) {
// dfsGT(S[i]);
// nrCTC++;
// }
// }
}
*/
int main() {
int x, y;
fin >> n >> m;
for (int i=1; i<=m; i++) { // obs: in la[x], nodurile adiacente cu x nu se pun in ordine crescatoare, ci in ordinea citirii
fin >> x >> y;
la[x].push_back(y); // graf orientat
grafTranspus[y].push_back(x);
}
//Kosaraju();
for (int i=1; i<=n; i++) {
if (visited1[i] == 0) {
//cout << "->dfsG(" << i << ")\n";
dfsG(i);
}
}
reverse(S.begin(), S.end());
for (auto i: S) {
if (comp[i] == 0) {
//cout << "->dfsG(" << i << ")\n";
compCurenta ++;
dfsGT(i);
}
}
fout << compCurenta << endl;
for(int i = 1; i <= compCurenta; ++i) {
for(auto j: sol[i])
fout << j << " ";
fout << endl;
}
return 0;
}