Cod sursa(job #662210)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 16 ianuarie 2012 04:16:20
Problema Componente tare conexe Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.99 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <bitset>
#include <cstdlib>

#define MAXN	100001

using namespace std;

typedef unsigned int uint32;
typedef vector<vector<int> > Graph;
typedef vector<vector<int> > Scc;

bitset<MAXN> visitedNodes_1;
bitset<MAXN> visitedNodes_2;

uint32 uVerticesAdded = 0;
stack<uint32> stNodes;

template<typename T>
class CQueue
{
public:
	CQueue(const size_t cap) :
		current(0),
		capacity(cap),
		curSize(0)
	{
		Q = (T*)malloc((cap+1)*sizeof(T));
	}
	
	T front() const
	{
		return Q[current];
	}
	
	void push(const T& elem)
	{
		const size_t pos = (current+curSize) % capacity;
		curSize++;
		Q[pos] = elem;
	}
	
	void pop()
	{
		if (curSize != 0)
		{
			curSize--;
			current++;
			current %= capacity;
		}
	}
	
	bool empty() const
	{
		return (curSize == 0);
	}
	
	size_t size()
	{
		return curSize;
	}
	
	void clear()
	{
		current = 0;
		curSize = 0;
	}
	
	~CQueue()
	{
		free(Q);
	}

private:
	T* Q;
	size_t current;
	size_t capacity;
	size_t curSize;
};

void Kosaraju_1(const Graph& graph, const uint32 node)
{
	//if (uVerticesAdded < graph.size())
	{
		for (uint32 i=0; i<graph[node].size(); ++i)
		{
			if (false == visitedNodes_1[graph[node][i]])
			{
				visitedNodes_1[graph[node][i]] = true;
				Kosaraju_1(graph, graph[node][i]);
			}
		}
		
		uVerticesAdded++;
		//cout << "Added node = " << node << endl;
		stNodes.push(node);
	}
}

void Kosaraju_2(const Graph& graph, vector<int>& scc, uint32 node)
{
	CQueue<uint32> Q(MAXN);
	
	scc.push_back(node);
	visitedNodes_2[node] = true;
	Q.push(node);
	
	while (!Q.empty())
	{
		node = Q.front();
		Q.pop();
		
		for (uint32 i=0; i<graph[node].size(); ++i)
		{
			if (false == visitedNodes_2[graph[node][i]])
			{
				scc.push_back(graph[node][i]);
				visitedNodes_2[graph[node][i]] = true;
				Q.push(graph[node][i]);
			}
		}
	}
}

int main()
{
	uint32 n, m, numComp=0;
	Graph graph, graphT;
	Scc sccs;
	fstream fin("ctc.in", fstream::in);
	fstream fout("ctc.out", fstream::out);
	
	fin >> n >> m;
	//cout << n << " " << m << endl;
	
	graph.resize(n);
	graphT.resize(n);
	sccs.resize(n);
	
	//cout << graph.size() << endl;
	
	for (uint32 i=0; i<m; ++i)
	{
		uint32 x, y;
		fin >> x >> y;
		
		graph[x-1].push_back(y-1);
		graphT[y-1].push_back(x-1);
	}
	
	for (uint32 i=0; i<n; ++i)
	{
		if (false == visitedNodes_1[i])
		{
			visitedNodes_1[i] = true;
			Kosaraju_1(graph, i);
		}
	}
	
	while (!stNodes.empty())
	{
		const uint32 node = stNodes.top();
		stNodes.pop();
		
		//cout << node << endl;

		if (false == visitedNodes_2[node])
		{
			Kosaraju_2(graphT, sccs[numComp], node);
			numComp++;
		}
	}
	
	fout << numComp << "\n";
	for (uint32 i=0; i<numComp; ++i)
	{
		for (uint32 j=0; j<sccs[i].size(); ++j)
		{
			fout << sccs[i][j]+1 << " ";
		}
		fout << "\n";
	}
	
	fin.close();
	fout.close();
	return 0;
}