Cod sursa(job #1801057)

Utilizator lorundlorund lorund Data 8 noiembrie 2016 16:47:15
Problema Componente tare conexe Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 12.67 kb
#ifndef GRAPH_H
#define GRAPH_H

#include <algorithm>
#include <vector>
#include <stack>
#include <unordered_map>

namespace GML {
	namespace Utils {
		template <typename type, typename weight = void>
		class StronglyConnectedComponents;


		// Weighted Graph class
		/**
		Weighted Graph class
		*/
		template <typename type, typename weight = void>
		class Graph {
			typedef bool(*Predicate) (const type &src, const type &dst, const weight &edge);
			friend class StronglyConnectedComponents<type, weight>;
		public:
			// construction
			Graph();
			Graph(size_t size, type start = type());
			void clear();
			void assign(size_t size, type start = type());
			Graph<type, weight> subgraph(const std::vector<type> &vertices) const;

			// iterator access
			class iterator;
			iterator begin(type vertex) const { return iterator(this, v2i.at(vertex), 0); }
			iterator end(type vertex) const { return iterator(this, v2i.at(vertex), adj[v2i.at(vertex)].size()); }

			// access
			size_t size() const;

			// manipulation
			void add_vertex(type vertex);
			void add_edge(type src, type dst, weight w);
			void remove_edge_if(Predicate pred);

		private:
			std::unordered_map<type, size_t> v2i; // vertex to index mapping
			std::unordered_map<size_t, type> i2v; // index to vertex mapping
			std::vector<std::vector<size_t>> adj; // adjacency list
			std::vector<std::vector<weight>> wts; // weights list
		};

		template <typename type, typename weight>
		Graph<type, weight>::Graph() {}
		template <typename type, typename weight>
		Graph<type, weight>::Graph(size_t size, type start) { assign(size, start); }
		template <typename type, typename weight>
		void Graph<type, weight>::clear() {
			v2i.clear();
			i2v.clear();
			adj.clear();
			wts.clear();
		}
		template <typename type, typename weight>
		void Graph<type, weight>::assign(size_t size, type start) {
			type tr;

			clear();
			for (tr = start; size; tr++, size--) {
				add_vertex(tr);
			}
		}
		template <typename type, typename weight>
		Graph<type, weight> Graph<type, weight>::subgraph(const std::vector<type> &vertices) const {
			Graph<type, weight> graph;
			size_t tr, gr, src, dst;

			for (tr = 0; tr < vertices.size(); ++tr) {
				graph.add_vertex(vertices[tr]);
			}

			for (tr = 0; tr < vertices.size(); ++tr) {
				src = v2i.at(vertices[tr]);
				for (gr = 0; gr < adj[src].size(); ++gr) {
					dst = adj[tr][gr];
					if (graph.v2i.count(i2v.at(dst))) {
						graph.add_edge(vertices[tr], i2v.at(dst), wts[tr][gr]);
					}
				}
			}

			return graph;
		}

		template <typename type, typename weight>
		class Graph<type, weight>::iterator : public std::iterator<std::input_iterator_tag, std::pair<type, weight>> {
		private:
			const Graph *m_graph;
			std::vector<size_t>::const_iterator m_itr_adj;
			typename std::vector<weight>::const_iterator m_itr_wts;
			std::pair<type, weight> m_value;
		public:
			iterator(const Graph *m_graph, size_t vertex, size_t index) : m_graph(m_graph), m_itr_adj(m_graph->adj[vertex].begin() + index), m_itr_wts(m_graph->wts[vertex].begin() + index) {}

			iterator& operator++() {
				m_itr_adj++;
				m_itr_wts++;
				return *this;
			}
			iterator& operator--() {
				m_itr_adj--;
				m_itr_wts--;
				return *this;
			}
			bool operator==(const iterator& other) const {
				return m_itr_adj == other.m_itr_adj;
			}
			bool operator!=(const iterator& other) const {
				return !(*this == other);
			}
			std::pair<type, weight> operator*() {
				m_value.first = m_graph->i2v.at(*m_itr_adj);
				m_value.second = *m_itr_wts;
				return m_value;
			}
			std::pair<type, weight>* operator->() {
				m_value.first = m_graph->i2v.at(*m_itr_adj);
				m_value.second = *m_itr_wts;
				return &m_value;
			}
		};

		template <typename type, typename weight>
		size_t Graph<type, weight>::size() const { return v2i.size(); }

		template <typename type, typename weight>
		void Graph<type, weight>::add_vertex(type vertex) {
			size_t size = this->size();
			v2i[vertex] = size;
			i2v[size] = vertex;
			adj.emplace_back(std::vector<size_t>());
			wts.emplace_back(std::vector<weight>());

		}
		template <typename type, typename weight>
		void Graph<type, weight>::add_edge(type src, type dst, weight w) {
			size_t src_index = v2i[src];
			size_t dst_index = v2i[dst];
			adj[src_index].emplace_back(dst_index);
			wts[src_index].emplace_back(w);
		}
		template <typename type, typename weight>
		void Graph<type, weight>::remove_edge_if(Predicate pred) {
			size_t tr, gr;
			type src, dst;

			for (tr = 0; tr < size(); ++tr) {
				src = i2v[tr];
				for (gr = 0; gr < adj[tr].size(); ++gr) {
					dst = i2v[adj[tr][gr]];
					if (pred(src, dst, wts[tr][gr])) {
						std::swap(adj[tr][gr], adj[tr].back());
						std::swap(wts[tr][gr], wts[tr].back());
						adj[tr].pop_back();
						wts[tr].pop_back();
					}
				}
			}
		}




		// Graph class
		/**
		Graph class
		*/
		template <typename type>
		class Graph<type, void> {
			typedef bool(*Predicate) (const type &src, const type &dst);
			friend class StronglyConnectedComponents<type>;
		public:
			// construction
			Graph();
			Graph(size_t size, type start = type());
			Graph<type> subgraph(const std::vector<type> &vertices) const;

			// iterator access
			class iterator;
			iterator begin(type vertex) const { return iterator(this, v2i.at(vertex), 0); }
			iterator end(type vertex) const { return iterator(this, v2i.at(vertex), adj[v2i.at(vertex)].size()); }

			// access
			size_t size() const;

			// manipulation
			void add_vertex(type vertex);
			void add_edge(type src, type dst);
			void remove_edge_if(Predicate pred);

		private:
			std::unordered_map<type, size_t> v2i; // vertex to index mapping
			std::unordered_map<size_t, type> i2v; // index to vertex mapping
			std::vector<std::vector<size_t>> adj; // adjacency list
		};

		template <typename type>
		Graph<type, void>::Graph() {}
		template <typename type>
		Graph<type, void>::Graph(size_t size, type start) {
			type tr;

			for (tr = start; size; tr++, size--) {
				add_vertex(tr);
			}
		}
		template <typename type>
		Graph<type> Graph<type, void>::subgraph(const std::vector<type> &vertices) const {
			Graph<type> graph;
			size_t tr, gr, src, dst;

			for (tr = 0; tr < vertices.size(); ++tr) {
				graph.add_vertex(vertices[tr]);
			}

			for (tr = 0; tr < vertices.size(); ++tr) {
				src = v2i.at(vertices[tr]);
				for (gr = 0; gr < adj[src].size(); ++gr) {
					dst = adj[tr][gr];
					if (graph.v2i.count(i2v.at(dst))) {
						graph.add_edge(vertices[tr], i2v.at(dst));
					}
				}
			}

			return graph;
		}

		template <typename type>
		class Graph<type, void>::iterator : public std::iterator<std::input_iterator_tag, type> {
		private:
			const Graph *m_graph;
			std::vector<size_t>::const_iterator m_itr;
			type m_value;
		public:
			iterator(const Graph *m_graph, size_t vertex, size_t index) : m_graph(m_graph), m_itr(m_graph->adj[vertex].begin() + index) {}

			iterator& operator++() {
				m_itr++;
				return *this;
			}
			iterator& operator--() {
				m_itr--;
				return *this;
			}
			bool operator==(const iterator& other) const {
				return m_itr == other.m_itr;
			}
			bool operator!=(const iterator& other) const {
				return !(*this == other);
			}
			type& operator*() {
				m_value = m_graph->i2v.at(*m_itr);
				return m_value;
			}
		};

		template <typename type>
		size_t Graph<type, void>::size() const { return v2i.size(); }

		template <typename type>
		void Graph<type, void>::add_vertex(type vertex) {
			size_t size = this->size();
			v2i[vertex] = size;
			i2v[size] = vertex;
			adj.emplace_back(std::vector<size_t>());

		}
		template <typename type>
		void Graph<type, void>::add_edge(type src, type dst) {
			size_t src_index = v2i[src];
			size_t dst_index = v2i[dst];
			adj[src_index].emplace_back(dst_index);
		}
		template <typename type>
		void Graph<type, void>::remove_edge_if(Predicate pred) {
			size_t tr, gr;
			type src, dst;

			for (tr = 0; tr < size(); ++tr) {
				src = i2v[tr];
				for (gr = 0; gr < adj[tr].size(); ++gr) {
					dst = i2v[adj[tr][gr]];
					if (pred(src, dst)) {
						std::swap(adj[tr][gr], adj[tr].back());
						adj[tr].pop_back();
					}
				}
			}
		}

		template <typename type, typename weight>
		class StronglyConnectedComponents {
		public:
			static std::vector<size_t> TopologicalSort(const Graph<type, weight> &graph) {
				std::vector<size_t> result;
				std::stack<std::pair<size_t, size_t>> st;
				std::vector<bool> visited(graph.size());
				size_t tr, size = graph.size();

				for (tr = 0; tr<size; ++tr) {
					if (!visited[tr]) {
						st.push(std::make_pair(tr, 0));
						visited[tr] = true;
						while (st.size()) {
							unsigned gr = st.top().first; // current node
							unsigned &br = st.top().second; // adjacency list index

							if (br < graph.adj[gr].size()) {
								if (!visited[graph.adj[gr][br]]) {
									visited[graph.adj[gr][br]] = true;
									st.push(std::make_pair(graph.adj[gr][br], 0));
								}
								++br;
							}
							else {
								st.pop();
								result.push_back(gr);
							}
						}
					}
				}
				std::reverse(result.begin(), result.end());

				return result;
			}
			static std::vector<std::vector<type>> build(const Graph<type, weight> &graph) {
				std::vector<unsigned> tsorted;
				std::vector<std::vector<unsigned>> tgraph(graph.size());;
				std::vector<bool> visited(graph.size());
				unsigned tr, gr, br;
				std::vector<std::vector<type>> components;

				tsorted = TopologicalSort(graph);
				for (tr = 0; tr<graph.size(); ++tr) {
					for (gr = 0; gr<graph.adj[tr].size(); ++gr) {
						tgraph[graph.adj[tr][gr]].push_back(tr);
					}
				}
				for (tr = 0; tr<tsorted.size(); ++tr) {
					if (!visited[tsorted[tr]]) {
						components.push_back(std::vector<unsigned>());
						std::vector<unsigned> &component = components.back();

						component.push_back(tsorted[tr]);
						visited[tsorted[tr]] = true;
						for (gr = 0; gr<component.size(); ++gr) {
							for (br = 0; br<tgraph[component[gr]].size(); ++br) {
								if (!visited[tgraph[component[gr]][br]]) {
									visited[tgraph[component[gr]][br]] = true;
									component.push_back(tgraph[component[gr]][br]);
								}
							}
						}
					}
				}

				for (tr = 0; tr < components.size(); ++tr) {
					for (gr = 0; gr < components[tr].size(); ++gr) {
						components[tr][gr] = graph.i2v.at(components[tr][gr]);
					}
				}

				return components;
			}
			/*static std::vector<std::vector<type>> build(const Graph<type, weight> &graph) {
			size_t tr, size = graph.size();
			size_t src, dst;
			std::vector<bool> onStack(size);
			std::vector<size_t> disc(size), low(size); // discovery, lowestAccessibleDisc
			std::stack<std::pair<size_t, size_t>> bk;
			std::stack<size_t> st;
			std::vector<std::vector<type>> components;

			for (tr = 0; tr < size; ++tr) {
			if (!disc[tr]) {
			size_t time = 0;

			disc[tr] = low[tr] = ++time;
			onStack[tr] = true;
			bk.push(std::make_pair(tr, 0));
			st.push(tr);

			while (bk.size()) {
			src = bk.top().first;
			if (bk.top().second < graph.adj[src].size()) {
			dst = graph.adj[src][bk.top().second++];
			if (!disc[dst]) {
			low[dst] = disc[dst] = ++time;
			onStack[dst] = true;
			bk.push(std::make_pair(dst, 0));
			st.push(dst);
			}
			else if (onStack[dst]) {
			low[src] = std::min(low[src], low[dst]);
			}
			}
			else {
			if (disc[src] == low[src]) {
			components.push_back(std::vector<type>());
			size_t node;
			do {
			components.back().push_back(graph.i2v.at(node = st.top()));
			onStack[node] = false;
			st.pop();
			} while (node != src);
			}
			bk.pop();
			if (bk.size()) {
			dst = src;
			src = bk.top().first;
			low[src] = std::min(low[src], low[dst]);
			}
			}
			}
			}
			}
			return components;
			}*/
		};

	} // namespace Utils
} // namespace GML

#endif // GRAPH_H

#include <fstream>
using namespace std;

int main()
{
	ifstream fin("ctc.in");
	ofstream fout("ctc.out");

	size_t n, m;
	GML::Utils::Graph<size_t> g;

	fin >> n >> m;
	for (size_t i = 1; i <= n; ++i) {
		g.add_vertex(i);
	}

	for (size_t i = 1; i <= m; ++i) {
		size_t src, dst;
		fin >> src >> dst;
		g.add_edge(src, dst);
	}

	vector<vector<size_t>> components = GML::Utils::StronglyConnectedComponents<size_t>::build(g);

	fout << components.size() << "\n";
	for (size_t i = 0; i < components.size(); ++i) {
		for (size_t j = 0; j < components[i].size(); ++j) {
			fout << components[i][j] << " ";
		}
		fout << "\n";
	}

	return 0;
};