Cod sursa(job #774350)

Utilizator darrenRares Buhai darren Data 4 august 2012 14:03:08
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <cstring>
#include <fstream>
#include <algorithm>
#include <set>
#include <vector>

using namespace std;

int N, M, TS;
vector<int> V[32002], P[32002], Q[32002];
set<int> W[32002];
int nodv[32002], minv[32002], where[32002], comps;
int T[32002], Tn[32002], in[32002], out[32002], timp;
int level[32002], lowest[32002];
int str[32002][16];
bool S[32002];
int ST[32002], STP[32002], K[32002];

class compare
{
	public: inline bool operator () (const int& i1, const int& i2)
	{
		return K[i1] < K[i2];
	}
};

inline bool is_str(int x, int y)
{
	return in[x] <= in[y] && out[x] >= out[y];
}

void Tarjan(int x)
{
	S[x] = true;
	nodv[x] = ++nodv[0];
	minv[x] = nodv[x];
	ST[++ST[0]] = x;
	
	for (vector<int>::iterator it = V[x].begin(); it != V[x].end(); ++it)
	{
		if (!S[*it]) Tarjan(*it);
		if (where[*it] == 0) minv[x] = min(minv[x], minv[*it]);
	}
	
	if (nodv[x] == minv[x])
	{
		++comps;
		while (ST[ST[0]] != x)
		{
			where[ST[ST[0]]] = comps;
			--ST[0];
		}
		where[ST[ST[0]]] = comps;
		--ST[0];
	}
}
void sortT(int x)
{
	S[x] = true;
	for (set<int>::iterator it = W[x].begin(); it != W[x].end(); ++it)
		if (!S[*it])
			sortT(*it);
	ST[++ST[0]] = x;
}
void Dfs(int x)
{
	S[x] = true;
	
	in[x] = ++timp;
	if (x != ST[ST[0]])
		lowest[x] = Tn[x];
	
	for (vector<int>::iterator it = P[x].begin(); it != P[x].end(); ++it)
	{
		if (!S[*it])
		{
			Tn[*it] = x;
			level[*it] = level[x] + 1;
			Dfs(*it);
			
			if (x != ST[ST[0]])
				if (level[lowest[*it]] < level[lowest[x]])
					lowest[x] = lowest[*it];
		}
		
		if (x != ST[ST[0]])
			if (level[*it] < level[lowest[x]])
				lowest[x] = *it;
	}
	
	out[x] = ++timp;
}
void goDfs(int x)
{
	STP[++STP[0]] = x;
	for (vector<int>::iterator it = Q[x].begin(); it != Q[x].end(); ++it)
	{
		T[*it] = x;
		goDfs(*it);
	}
	--STP[0];
	
	for (int i = 0; i <= 15; ++i)
	{
		if (STP[0] >= (1 << i)) str[x][i] = STP[STP[0] - (1 << i) + 1];
		else                    str[x][i] = ST[ST[0]];
	}
}

int main()
{
	ifstream fin("obiective.in");
	ofstream fout("obiective.out");
	
	fin >> N >> M;
	for (int i = 1, nod1, nod2; i <= M; ++i)
	{
		fin >> nod1 >> nod2;
		V[nod1].push_back(nod2);
	}
	for (int i = 1; i <= N; ++i)
		if (!S[i])
			Tarjan(i);
	
	for (int i = 1; i <= N; ++i)
		for (vector<int>::iterator it = V[i].begin(); it != V[i].end(); ++it)
			if (where[*it] != where[i])
				W[where[i]].insert(where[*it]);
	
	memset(S, 0, sizeof(S));
	ST[0] = 0;
	
	for (int i = 1; i <= comps; ++i)
		if (!S[i])
			sortT(i);
	
	for (int i = ST[0]; i >= 1; --i)
		K[ST[i]] = ST[0] - i + 1;
	
	for (int i = 1; i <= comps; ++i)
	{
		for (set<int>::iterator it = W[i].begin(); it != W[i].end(); ++it)
		{
			P[i].push_back(*it);
			P[*it].push_back(i);
		}
		sort(P[i].begin(), P[i].end(), compare());
	}
	
	memset(S, 0, sizeof(S));
	Dfs(ST[ST[0]]);
	
	for (int i = 1; i <= comps; ++i)
		if (lowest[i] != 0)
			Q[lowest[i]].push_back(i);
	
	goDfs(ST[ST[0]]);
	
	fin >> TS;
	for (int i = 1, nod1, nod2; i <= TS; ++i)
	{
		fin >> nod1 >> nod2;
		nod1 = where[nod1], nod2 = where[nod2];
		
		if (is_str(nod1, nod2)) fout << 0 << '\n';
		else
		{
			int nodnow = nod1, steps = 0;
			for (int j = 15; j >= 0; --j)
				if (!is_str(str[nodnow][j], nod2))
				{
					nodnow = str[nodnow][j];
					steps += (1 << j);
				}
			nodnow = T[nodnow];
			++steps;
			
			fout << steps << '\n';
		}
	}
	
	fin.close();
	fout.close();
}