Pagini recente » Cod sursa (job #974954) | Cod sursa (job #429780) | Cod sursa (job #3234837) | Cod sursa (job #2082397) | Cod sursa (job #3272121)
#include <fstream>
#include <vector>
#include <algorithm>
#define maxi 100001
using namespace std;
ifstream fin("ctc.in");
ofstream fout("ctc.out");
class Graf {
int nrNoduri, nrMuchii; // Numarul de noduri si muchii
int x, y; // Nodurile unei muchii (x -> y)
vector<int> *adiacenta; // Lista de adiacenta pentru graf
vector<int> *adiacenta2; // Lista de adiacenta pentru graful transpus
int vizitat[maxi] = {0}; // Vector pentru marcarea nodurilor vizitate
public:
Graf();
~Graf();
void citireComponenteTareConexe(); // Citirea grafului orientat
void DF1(int nodPlecare, vector<int> &succesor, vector<int> &v, int &index); // DFS pe graful initial
void DF2(int nodPlecare, vector<int> &predecesor, int &nrComponenteTareConexe); // DFS pe graful transpus
void afisareComponenteTareConexe(); // Determinarea si afisarea componentelor tare conexe
};
Graf::Graf() {
nrNoduri = nrMuchii = x = y = 0;
adiacenta = new vector<int>[maxi]; // Alocare memorie pentru lista de adiacenta
adiacenta2 = new vector<int>[maxi]; // Alocare memorie pentru lista de adiacenta transpus
}
Graf::~Graf() {
delete[] adiacenta; // Eliberare memorie pentru lista de adiacenta
delete[] adiacenta2; // Eliberare memorie pentru lista de adiacenta transpus
}
// Citirea grafului orientat si construirea grafului transpus
void Graf::citireComponenteTareConexe() {
fin >> nrNoduri >> nrMuchii; // Citim numarul de noduri si muchii
for (int i = 1; i <= nrMuchii; i++) {
fin >> x >> y; // Citim fiecare muchie (x -> y)
adiacenta[x].push_back(y); // Adaugam nodul y ca succesor al lui x
adiacenta2[y].push_back(x); // Adaugam nodul x ca succesor al lui y in graful transpus
}
}
// DFS pe graful initial pentru a construi ordinea nodurilor
void Graf::DF1(int nodPlecare, vector<int> &succesor, vector<int> &v, int &index) {
succesor[nodPlecare] = 1; // Marcam nodul ca vizitat
for (auto i : adiacenta[nodPlecare]) { // Parcurgem toti vecinii nodului curent
if (!succesor[i]) {
DF1(i, succesor, v, index); // Apel recursiv pentru vecinul curent
}
}
v[++index] = nodPlecare; // Adaugam nodul in ordinea finala (postordine DFS)
}
// DFS pe graful transpus pentru a determina componentele tare conexe
void Graf::DF2(int nodPlecare, vector<int> &predecesor, int &nrComponenteTareConexe) {
predecesor[nodPlecare] = nrComponenteTareConexe; // Marcam componenta nodului curent
for (auto i : adiacenta2[nodPlecare]) { // Parcurgem toti vecinii in graful transpus
if (!predecesor[i]) {
DF2(i, predecesor, nrComponenteTareConexe); // Apel recursiv pentru vecinul curent
}
}
}
// Determinarea si afisarea componentelor tare conexe folosind algoritmul Kosaraju
void Graf::afisareComponenteTareConexe() {
vector<int> succesor(nrNoduri + 1, 0); // Vector pentru a marca vizitarea nodurilor in primul DFS
vector<int> predecesor(nrNoduri + 1, 0); // Vector pentru a marca componentele nodurilor in al doilea DFS
vector<int> v(nrNoduri + 1, 0); // Vector pentru a stoca ordinea nodurilor din primul DFS
pair<int, int> p[nrNoduri + 1]; // Perechi pentru sortarea nodurilor dupa componente
int nrComponenteTareConexe = 1, index = 0;
// Primul DFS pe graful initial pentru a construi ordinea nodurilor
for (int i = 1; i <= nrNoduri; i++) {
if (succesor[i] == 0) {
DF1(i, succesor, v, index);
}
}
// Al doilea DFS pe graful transpus pentru a determina componentele tare conexe
for (int i = nrNoduri; i >= 1; i--) {
if (predecesor[v[i]] == 0) {
DF2(v[i], predecesor, nrComponenteTareConexe);
nrComponenteTareConexe++;
}
}
// Afisam numarul de componente tare conexe
fout << nrComponenteTareConexe - 1 << '\n';
// Sortam nodurile in functie de componente
for (int i = 1; i <= nrNoduri; i++) {
p[i].first = predecesor[i]; // Componenta nodului curent
p[i].second = i; // Valoarea nodului curent
}
sort(p + 1, p + nrNoduri + 1); // Sortam nodurile dupa componenta lor
// Afisam nodurile din fiecare componenta tare conexa
for (int i = 1; i <= nrNoduri; i++) {
if (p[i].first != p[i + 1].first) {
fout << p[i].second << '\n';
} else {
fout << p[i].second << " ";
}
}
}
int main() {
Graf g1; // Cream un obiect al clasei Graf
g1.citireComponenteTareConexe(); // Citim graful orientat si graful transpus
g1.afisareComponenteTareConexe(); // Determinam si afisam componentele tare conexe
fin.close(); // Inchidem fisierul de intrare
fout.close(); // Inchidem fisierul de iesire
return 0;
}