Cod sursa(job #2487831)

Utilizator AndreiM.Andrei Moldoveanu AndreiM. Data 5 noiembrie 2019 19:44:02
Problema Componente tare conexe Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.3 kb
//Cerchez 3 - tare-conexitate + pdf graf_definitii
//Desc unui graf orientat in componente tare-conexe
//Complexitatea alg este:
//	cu liste de adiacenta - O(n+m)
//	cu matricea de adiacenta - probabil O(n^2)
//--> reprezentare prin lista de adiacenta - dinamic
/*
1. Parcurg graful in adancime si numerotez vf grafului in postordine - in ordinea crescatoare a timpilor de finish
	- varful x este numerotat dupa ce toti succesorii sai au fost numerotati
2. Se determina graful transpus AT ( il initializez inca de la citire)
3. Se parcurge graful TRANSPUS in adancime, considerand vf in ordinea inversa a vizitarii lor in parcurgerea DFS a grafului initial
	- in ordinea din vectorul postordine
4. Fiecare subgraf obtinut in parcurgerea DFS a grafului transpus reprezinta componenta tare-conexa a grafului initial
*/
#include <iostream>
#include <vector>
#include <fstream>
#define NMax 100005
using namespace std;

//vector comp conexe
vector<vector<int>> vecConnex;

int n, nr, nrc;
int *A[NMax], *AT[NMax];
int postordine[NMax], viz[NMax];
void citire();
void afisare(int);
void DFS(int);
void DFST(int);

int* myRealloc(int*, int);

int main()
{
	citire();
	//parcurgem graful DFS, determinand ordinea varfurilor
	for (int i = 1; i <= n; i++)
		if (!viz[i]) DFS(i);

	//parcurgem DFS graful transpus, prelucrand varfurile in postordine
	for (int i = n; i > 0; i--)
		if (viz[postordine[i]])
			//componenta tare-conexa din care face parte varful curent nu a fost determinata
		{
			//cout << "Componenta tare-conexa " << ++nrc << ": ";
			++nrc;
			vecConnex.push_back(vector<int>());
			DFST(postordine[i]);
		}
	afisare(nrc);

	return 0;
}

//init listele de adiacenta - A si AT(graful transpus)
void citire()
{
	fstream fin("ctc.in");
	int x, y, m;
	fin >> n >> m;
	//aloc memorie pentru fiecare varf
	for (int i = 1; i <= n; i++)
	{
		A[i] = new int[1];
		A[i][0] = 0;
		AT[i] = new int[1];
		AT[i][0] = 0;
	}

	for (int i = 0; i < m; i++)
	{
		fin >> x >> y;

		//initializez lista de adiacenta
		A[x][0]++;
		A[x] = myRealloc(A[x], A[x][0] + 1);
		A[x][A[x][0]] = y;

		//iinitializez list de adiacenta a grafului TRANSPUS AT
		AT[y][0]++;
		AT[y] = myRealloc(AT[y], AT[y][0] + 1);
		AT[y][AT[y][0]] = x;
	}
	fin.close();
}

//parcurgerea in adancime si numerotarea vf in ordinea crescatoare a timpilor de finish
void DFS(int x)
{
	viz[x] = 1;
	for (int i = 1; i <= A[x][0]; i++)
		if (!viz[A[x][i]])
			DFS(A[x][i]);
	postordine[++nr] = x;
}

//parcurgerea grafului TRANSPUS in adancime (DFST) considerand vf in ordinea inversa a viz lor in parcurgerea DFS
//(parcurgerea in ordinea din vectorul postordine)
void DFST(int x)
{
	viz[x] = 0;
	vecConnex.back().push_back(x);
	//cout << x << ' ';
	for (int i = 1; i <= AT[x][0]; i++)
		if (viz[AT[x][i]])
			DFST(AT[x][i]);
}

int* myRealloc(int A[], int newSize)
{
	int* tmp = new int[newSize];

	while (--newSize >= 0)
	{
		tmp[newSize] = A[newSize];
	}
	delete[] A;
	A = tmp;
	return A;
}

void afisare(int)
{
	ofstream fout("ctc.out");
	fout << nrc<<endl;
	for (std::vector<vector<int>>::iterator it = vecConnex.begin(); it != vecConnex.end(); ++it)
	{
		for (std::vector<int>::iterator it2 = it->begin(); it2 != it->end(); ++it2)
			fout << *it2<<' ';
		fout << endl;
	}
	fout.close();
}