Cod sursa(job #1712897)

Utilizator retrogradLucian Bicsi retrograd Data 4 iunie 2016 00:34:50
Problema Componente tare conexe Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.02 kb
// Strongly connected components decomposition algorithm
// 
// Usage: 
// Initialize with constructor as the number of nodes
// and add edges accordingly with the AddEdge(u, v) method.
// Then just run Reduce()
//
// ATTENTION: The reduced DAG may contain duplicate edges


#include <bits/stdc++.h>

using namespace std;

struct SCCWrapper {

	int n;
	vector<vector<int>> G, G_T;
	vector<bool> Viz;
	vector<int> Stack;


	vector<int> SCC;           // SCC[i] gives the scc id of node i
	vector<vector<int>> Nodes; // Nodes[i] is the list of nodes in scc i
	vector<vector<int>> G_R;   // The reduced DAG (MAY CONTAIN DUPLICATE EDGES)
	int scc;                   // Strongly connected component count

	SCCWrapper(int n) : n(n), Viz(n), G(n), G_T(n), SCC(n) {
		Stack.reserve(n);
		scc = 0;
	};

	void AddEdge(int a, int b) {
		G[a].push_back(b);
		G_T[b].push_back(a);
	}

	void dfs_forward(int node) {
		Viz[node] = true;
		for(auto vec : G[node]) {
			if(!Viz[vec])
				dfs_forward(vec);
		}
		Stack.push_back(node);
	}

	void dfs_backward(int node) {
		Viz[node] = true;
		SCC[node] = scc;
		Nodes[scc].push_back(node);

		for(auto vec : G_T[node]) {
			if(!Viz[vec])
				dfs_backward(vec);
		}
	}

	void Reduce() {
		fill(Viz.begin(), Viz.end(), 0);
		for(int i = 0; i < n; ++i)
			if(!Viz[i])
				dfs_forward(i);

		assert(Stack.size() == n);

		fill(Viz.begin(), Viz.end(), 0);
		for(int i = n - 1; i >= 0; --i)
			if(!Viz[Stack[i]]) {
				Nodes.push_back(vector<int>());
				dfs_backward(Stack[i]);
				++scc;
			}

		G_R.resize(scc);
		for(int i = 0; i < n; ++i) {
			for(auto vec : G[i])
				G_R[SCC[i]].push_back(SCC[vec]);
		}
	}

};

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

	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n, m, a, b;
	cin >> n >> m;
	SCCWrapper graph(n);

	while(m--) {
		cin >> a >> b;
		graph.AddEdge(a - 1, b - 1);
	}

	graph.Reduce();
	cout << graph.scc << '\n';

	for(auto scc : graph.Nodes) {
		for(auto node : scc) {
			cout << node + 1 << " ";
		}
		cout << '\n';
	}

	return 0;
}