Cod sursa(job #1689383)

Utilizator lorundlorund lorund Data 14 aprilie 2016 10:42:01
Problema Componente tare conexe Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 7.69 kb

#define _CRT_SECURE_NO_WARNINGS

#include <algorithm>
#include <vector>
#include <stack>
#include <unordered_map>
#define UInt32 unsigned

template <typename T>
class Graph {
protected:
	std::unordered_map<T, UInt32> nodeMap;
	std::unordered_map<UInt32, T> nodeInvMap;
	std::vector<std::vector<UInt32>> adj;

public:
	Graph() {}
	Graph(UInt32 nodesCnt) : Graph() { Create(nodesCnt); }
	Graph(const Graph<T> &other) : nodeMap(other.nodeMap), adj(other.adj) {}
	virtual ~Graph() {}

public:
	inline UInt32 Size() const { return nodeMap.size(); }
	inline bool addNode(T node) {
		UInt32 size = Size();
		nodeMap[node] = size;
		nodeInvMap[size] = node;
		return true;
	}
	inline bool addEdge(T src, T dst) {
		UInt32 srcIndex = src;
		UInt32 dstIndex = dst;
		adj[srcIndex].push_back(dstIndex);
		return true;
	}
	bool Create(UInt32 nodesCnt) {
		Clear();
		adj.resize(nodesCnt);
		for (UInt32 tr = 0; tr < nodesCnt; ++tr) addNode(tr);
		return true;
	}
	bool Clear() {
		adj.clear();
		return true;
	}

public:
	bool ConnectedComponents(std::vector<std::vector<UInt32>> &components) {
		std::vector<UInt32> parent;
		UInt32 parentFrom, parentTo, index;
		std::unordered_map<UInt32, UInt32> componentIndex;

		for (UInt32 i = 0; i<Size(); ++i) {
			parent.push_back(i);
		}

		for (UInt32 i = 0; i<Size(); ++i) {
			for (UInt32 j = 0; j<adj[i].size(); ++j) {
				parentFrom = i;
				parentTo = adj[i][j];

				while (parent[parentFrom] != parentFrom) {
					parentFrom = (parent[parentFrom] = parent[parent[parentFrom]]);
				}
				while (parent[parentTo] != parentTo) {
					parentTo = (parent[parentTo] = parent[parent[parentTo]]);
				}
				if (parentFrom != parentTo) {
					parent[parentFrom] = parentTo;
				}
			}
		}

		for (UInt32 i = 0; i<Size(); ++i) {
			parentFrom = parent[i];
			while (parent[parentFrom] != parentFrom) {
				parentFrom = (parent[parentFrom] = parent[parent[parentFrom]]);
			}
			if (!componentIndex.count(parentFrom)) {
				UInt32 index = componentIndex.size();
				componentIndex[parentFrom] = index;
				components.push_back(std::vector<UInt32>());
			}
			index = componentIndex[parentFrom];
			components[index].push_back(i);
		}
		return true;
	}
	bool StrongComponents(std::vector<std::vector<UInt32>> &components) {
		UInt32 tr, size = Size();
		UInt32 src, dst;
		std::vector<bool> onStack(size);
		std::vector<UInt32> disc(size), low(size); // discovery, lowestAccessibleDisc
		std::stack<std::pair<UInt32, UInt32>> bk;
		std::stack<UInt32> st;

		for (tr = 0; tr < size; ++tr) {
			if (!disc[tr]) {
				UInt32 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 < adj[src].size()) {
						dst = 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], disc[dst]);
						}
					}
					else {
						if (disc[src] == low[src]) {
							components.push_back(std::vector<UInt32>());
							UInt32 node;
							do {
								components.back().push_back(nodeInvMap[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 true;
	}
};


template <typename T, typename I>
class Graph<std::pair<T, I>> {
protected:
	std::unordered_map<T, UInt32> nodeMap;
	std::unordered_map<UInt32, T> nodeInvMap;
	std::vector<std::vector<std::pair<UInt32, I>>> adj;

public:
	Graph() {}
	Graph(UInt32 nodesCnt) : Graph() { Create(nodesCnt); }
	Graph(const Graph<T> &other) : nodeMap(other.nodeMap), adj(other.edges) {}
	virtual ~Graph() {}

public:
	inline UInt32 Size() const { return nodeMap.size(); }
	inline bool addNode(T node) {
		UInt32 size = Size();
		nodeMap[node] = size;
		nodeInvMap[size] = node;
		return true;
	}
	inline bool addEdge(T src, T dst) {
		UInt32 srcIndex = src;
		UInt32 dstIndex = dst;
		adj[srcIndex].push_back(dstIndex);
		return true;
	}
	bool Create(UInt32 nodesCnt) {
		Clear();
		adj.resize(nodesCnt);
		for (UInt32 tr = 0; tr < nodesCnt; ++tr) addNode(tr);
		return true;
	}

	bool Clear() {
		adj.clear();
		return true;
	}

public:
	bool ConnectedComponents(std::vector<std::vector<UInt32>> &components) {
		std::vector<UInt32> parent;
		UInt32 parentFrom, parentTo, index;
		std::unordered_map<UInt32, UInt32> componentIndex;

		for (UInt32 i = 0; i<Size(); ++i) {
			parent.push_back(i);
		}

		for (UInt32 i = 0; i<Size(); ++i) {
			for (UInt32 j = 0; j<adj[i].size(); ++j) {
				parentFrom = i;
				parentTo = adj[i][j].first;

				while (parent[parentFrom] != parentFrom) {
					parentFrom = (parent[parentFrom] = parent[parent[parentFrom]]);
				}
				while (parent[parentTo] != parentTo) {
					parentTo = (parent[parentTo] = parent[parent[parentTo]]);
				}
				if (parentFrom != parentTo) {
					parent[parentFrom] = parentTo;
				}
			}
		}

		for (UInt32 i = 0; i<Size(); ++i) {
			parentFrom = parent[i];
			while (parent[parentFrom] != parentFrom) {
				parentFrom = (parent[parentFrom] = parent[parent[parentFrom]]);
			}
			if (!componentIndex.count(parentFrom)) {
				UInt32 index = componentIndex.size();
				componentIndex[parentFrom] = index;
				components.push_back(std::vector<UInt32>());
			}
			index = componentIndex[parentFrom];
			components[index].push_back(i);
		}
		return true;
	}
	bool StrongComponents(std::vector<std::vector<UInt32>> &components) {
		UInt32 tr, size = Size();
		UInt32 src, dst;
		std::vector<bool> onStack(size);
		std::vector<UInt32> disc(size), low(size); // discovery, lowestAccessibleDisc
		std::stack<std::pair<UInt32, UInt32>> bk;
		std::stack<UInt32> st;

		for (tr = 0; tr < size; ++tr) {
			if (!disc[tr]) {
				UInt32 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 < adj[src].size()) {
						dst = adj[src][bk.top().second++].first;
						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], disc[dst]);
						}
					}
					else {
						if (disc[src] == low[src]) {
							components.push_back(std::vector<UInt32>());
							UInt32 node;
							do {
								components.back().push_back(nodeInvMap[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 true;
	}
};

int main(int argc, char *argv[])
{
	Graph<int> g;
	int n = 0, m = 0;
	std::vector<std::vector<unsigned>> components;

	freopen("ctc.in", "r", stdin);
	freopen("ctc.out", "w", stdout);

	scanf("%d %d", &n, &m);
	g.Create(n);
	for (int i = 0; i<m; ++i) {
		int x = 0, y = 0;

		scanf("%d %d", &x, &y);
		g.addEdge(x-1, y-1);
	}

	g.StrongComponents(components);
	printf("%d\n", components.size());
	for (unsigned i = 0; i<components.size(); ++i) {
		for (unsigned j = 0; j<components[i].size(); ++j) {
			printf("%d ", components[i][j] + 1);
		}
		puts("");
	}

	return 0;
}