#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;
};