Cod sursa(job #1727407)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 10 iulie 2016 18:33:02
Problema Obiective Scor 5
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.78 kb
#include <fstream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <map>

using namespace std;

ifstream fin("obiective.in");
ofstream fout("obiective.out");

const int dim = 32005;
const int dimLog = 17;

int n, m;
vector<int> g[dim];

int ctcCount, ctc[dim];

int low[dim], niv[dim], curNiv = 0;
stack<int> st;
void dfs(int node) {

	niv[node] = low[node] = ++curNiv;
	st.push(node);

	for (auto& it : g[node]) {

		if (niv[it] == 0)
			dfs(it);
		if (niv[it] > 0)
			low[node] = min(low[node], low[it]);

	}

	if (low[node] == niv[node]) {

		int x; ++ctcCount;
		do {

			x = st.top();
			st.pop();

			niv[x] *= -1;
			ctc[x] = ctcCount;

		} while (x != node);

	}

}

map< pair<int, int>, bool> memo;
vector<int> ctcG[dim];

int parent[dimLog][dim];

void buildCtcGraph(void) {

	for (int i = 1; i <= n; ++i)
		ctc[i] = ctcCount - ctc[i] + 1;

	for (int i = 1; i <= ctcCount; ++i)
		parent[0][i] = i;

	for (int i = 1; i <= n; ++i) {
		for (auto& it : g[i]) {

			if (ctc[i] == ctc[it] || memo[make_pair(ctc[i], ctc[it])])
				continue;

			memo[make_pair(ctc[i], ctc[it])] = true;
			ctcG[ctc[i]].push_back(ctc[it]);

			parent[0][ctc[it]] = min(parent[0][ctc[it]], ctc[i]);

		}
	}

}

int anc[dimLog][dim];
void dfsCtcG(int node, int lvl) {

	niv[node] = lvl;

	for (auto& it : ctcG[node]) {

		if (niv[it])
			continue;

		anc[0][it] = node;

		dfsCtcG(it, lvl + 1);

		parent[0][node] = min(parent[0][node], parent[0][it]);

	}

}

void initAnc(void) {

	for (int i = 1; i < dimLog; ++i)
		for (int j = 1; j <= ctcCount; ++j)
			anc[i][j] = anc[i - 1][anc[i - 1][j]];

}

void goUp(int& x, int howMuch) {

	for (int i = dimLog - 1; i >= 0; --i)
		if ((1 << i) <= howMuch)
			howMuch -= (1 << i), x = anc[i][x];

}

int lca(int x, int y) {

	if (niv[x] < niv[y])
		swap(x, y);

	goUp(x, niv[x] - niv[y]);

	if (x == y)
		return x;

	for (int i = dimLog - 1; i >= 0; --i) {

		if (parent[i][x] == parent[i][y])
			continue;

		x = parent[i][x];
		y = parent[i][y];

	}

	x = parent[0][x];

	return x;

}

int main() {

	fin >> n >> m;
	for (int i = 1; i <= m; ++i) {

		int x, y; fin >> x >> y;
		g[x].push_back(y);

	}

	for (int i = 1; i <= n; ++i)
		if (niv[i] == 0)
			dfs(i);

	buildCtcGraph();

	memset(niv, 0, sizeof niv);
	dfsCtcG(1, 1);
	initAnc();

	int t; fin >> t;
	while (t--) {

		int x, y; fin >> x >> y;
		x = ctc[x], y = ctc[y];

		int z = lca(x, y);

		if (x == z) {
			fout << "0\n";
			continue;
		}

		int sol = 1;
		for (int i = dimLog - 1; i >= 0; --i)
			if (parent[i][x] > z)
				sol += (1 << i), x = parent[i][x];

		fout << sol << '\n';

	}

	return 0;

}

//Trust me, I'm the Doctor!