Cod sursa(job #1769749)

Utilizator andreioneaAndrei Onea andreionea Data 3 octombrie 2016 03:03:34
Problema Componente tare conexe Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.08 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <utility>
#include <memory>
#include <iterator>
#include <stack>

namespace cpp14
{
	template <class T, class... Args>
	std::unique_ptr<T> make_unique(Args&&... args) {return std::unique_ptr<T>(new T(std::forward<Args>(args)...));}
};

struct file_manip {

	std::ifstream fin;
	std::ofstream fout;

	file_manip(const char* filename) {
		std::string infilename  = std::string(filename) + ".in";
		std::string outfilename = std::string(filename) + ".out";
		fin.open(infilename.c_str());
		fout.open(outfilename.c_str());
	}

	template <class T>
	file_manip& operator << (const T& rhs) {
		fout << rhs;
		return *this;
	}
	template <class T>
	file_manip& operator >> (T& rhs) {
		fin >> rhs;
		return *this;
	}

	template <class T>
	std::ostream_iterator<T> GetOstreamIterator() {
		return std::ostream_iterator<T>(fout);
	} 

	template <class T>
	std::istream_iterator<T> GetIstreamIterator() {
		return std::istream_iterator<T>(fin);
	}

	template <class T>
	std::vector<T> ReadVector(int size)
	{
		std::vector<int> v;
		v.reserve(size);
		std::copy_n(GetIstreamIterator<int>(), size, std::back_inserter(v));
		return v;
	}
};

struct Graph
{
	struct Vertex
	{
		static const auto UndefinedIndex = -1;
		int index = UndefinedIndex, low_link = UndefinedIndex;
		bool on_stack = false;
		std::vector<int> neighbors;
		int val;
		Vertex(int val) : val(val) { }
		void AddNeighbor(int x) { neighbors.push_back(x); }
	};

	std::vector<Vertex> vertices;
	int N;

	int index;
	std::stack<int> S;
	std::vector<int> solution;
	void Init();
	void Tarjan(file_manip& fm);
	void StrongConnect(Vertex& v);
};

template <>
file_manip& file_manip::operator >> (Graph& rhs) {
	fin >> rhs.N;
	rhs.Init();
	int M;
	fin >> M;
	while (M--)
	{
		int A, B;
		fin >> A >> B;
		rhs.vertices[A - 1].AddNeighbor(B - 1);
	}
	return *this;
}

void Graph::Init()
{
	vertices.reserve(N);
	for (int i = 0; i < N; ++i)
	{
		vertices.emplace_back(i);
	}
	solution.reserve(2 * N + 1);
	solution.push_back(0);
}

void Graph::Tarjan(file_manip& fm)
{
	index = 0;

	for (auto& v : vertices)
	{
		if (v.index == Vertex::UndefinedIndex)
		{
			StrongConnect(v);
		}
	}
	fm << solution[0] << "\n";
	for (auto i = 1; i < solution.size(); ++i)
	{
		if (solution[i] == -1)
			fm << "\n";
		else
			fm << solution[i] + 1 << " ";
	}
	solution.clear();
}

void Graph::StrongConnect(Vertex& v)
{
	v.index = index;
	v.low_link = index;
	++index;
	S.push(v.val);
	v.on_stack = true;

	for (const auto& w : v.neighbors)
	{
		if (vertices[w].index == Vertex::UndefinedIndex)
		{
			StrongConnect(vertices[w]);
			v.low_link = std::min(v.low_link, vertices[w].low_link);
		}
		else if (vertices[w].on_stack)
		{
			v.low_link = std::min(v.low_link, vertices[w].index);	
		}
	}

	if (v.low_link == v.index)
	{
		++solution[0];
		while (S.top() != v.val)
		{
			solution.push_back(S.top());
			vertices[S.top()].on_stack = false;
			S.pop();
		}
		solution.push_back(S.top());
		vertices[S.top()].on_stack = false;
		S.pop();
		solution.push_back(-1);
	}
}

int main()
{
	file_manip fm("ctc");
	Graph G;
	fm >> G;
	G.Tarjan(fm);
	return 0;
}