Cod sursa(job #1474500)

Utilizator tudi98Cozma Tudor tudi98 Data 22 august 2015 03:16:25
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.83 kb
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

const int Nmax = 32000;

int N,M,T,SCC = 0,root;
vector<int> Adj[Nmax+1],TAdj[Nmax+1];
bool seen[Nmax+1],come[Nmax+1];
stack<int> KosarajuST;
int comp[Nmax+1];
set<int> G[Nmax+1];
int ST[Nmax+1],K[Nmax+1];
vector<int> Graph[Nmax+1];
int Ancestor[16][Nmax+1],Up[16][Nmax+1],lvl[Nmax+1];

struct Compare
{
	inline bool operator()(const int& Rs,const int& Ls)
	{
		return K[Rs] < K[Ls];
	}
};

void Dfs1(int node)
{
	seen[node] = 1;
	for (vector<int>::iterator it = Adj[node].begin(); it != Adj[node].end(); ++it)
		if (!seen[*it])
			Dfs1(*it);
	KosarajuST.push(node);
}

void Dfs2(int node)
{
	comp[node] = SCC;
	for (vector<int>::iterator it = TAdj[node].begin(); it != TAdj[node].end(); ++it)
		if (!comp[*it])
			Dfs2(*it);
}

void Kosaraju()
{
	for (int i = 1; i <= N; ++i)
		if (!seen[i])
			Dfs1(i);

	while (!KosarajuST.empty())
	{
		if (!comp[KosarajuST.top()])
		{
		    ++SCC;   
			Dfs2(KosarajuST.top());
		}
		KosarajuST.pop();
	}	
}

void BuildDAG()
{
	for (int i = 1; i <= N; ++i)
		for (vector<int>::iterator it = Adj[i].begin(); it != Adj[i].end(); ++it)
			if(comp[i] != comp[*it]) 
				G[comp[i]].insert(comp[*it]);
}

void Tsort(int node)
{
	seen[node] = 1;
	for (set<int>::iterator it = G[node].begin(); it != G[node].end(); ++it)
		if (!seen[*it])
			Tsort(*it);
	ST[++ST[0]] = node;
}

void TopologicalSort()
{
	memset(seen, 0, sizeof seen);
	for (int i = 1; i <= SCC; ++i)
		if (!seen[i])
			Tsort(i);	

	root = ST[ST[0]];

	for (int i = 1; i <= ST[ST[0]]; ++i)
		K[ST[i]] = ST[0] - i + 1;

	for (int i = 1; i <= SCC; ++i)
	{
		Graph[i] = vector<int>(G[i].begin(),G[i].end());
		sort(Graph[i].begin(),Graph[i].end(),Compare());
	}
}
      
void BuildTree(int node)
{
	for (vector<int>::iterator it = Graph[node].begin(); it != Graph[node].end(); ++it)
	{
		if (!Ancestor[0][*it])
		{
			Ancestor[0][*it] = node;
			lvl[*it] = lvl[node] + 1;
			BuildTree(*it);
		}

		if (!Up[0][*it] || lvl[Up[0][*it]] > lvl[node])
			Up[0][*it] = node;

		if(node == Up[0][*it]) continue;

		if (!Up[0][node] || lvl[Up[0][node]] > lvl[Up[0][*it]])
			Up[0][node] = Up[0][*it];
	}	
}
        
void BuildLCA()
{
	for (int i = 1; (1 << i) <= SCC; ++i)
		for (int j = 1; j <= SCC; ++j)
		{
        	Ancestor[i][j] = Ancestor[i-1][Ancestor[i-1][j]];
        	Up[i][j] = Up[i-1][Up[i-1][j]];	
        }
}

int lca(int x,int y)
{
	if(lvl[x] < lvl[y])
		swap(x,y);
   	
   	int logx,logy;
   	for (logx = 1; 1 << logx < lvl[x]; ++logx);
   	for (logy = 1; 1 << logy < lvl[y]; ++logy);

   	for (;lvl[x] != lvl[y]; --logx)
   		if (lvl[x] - (1 << logx) >= lvl[y])
   			x = Ancestor[logx][x];

   	if (x == y) return x;

   	for (; logy >= 0; --logy)
   		if (Ancestor[logy][y] != Ancestor[logy][x])
   		{
   			y = Ancestor[logy][y];
   			x = Ancestor[logy][x];
		}

	return Ancestor[0][x];
}

int Solve(int from,int to)
{
	if (lvl[from] <= lvl[to]) return 0;

	int log;
	for (log = 1; (1 << log) <= lvl[from]; ++log);
	--log;

	int Ret = 0;
	for (; log >= 0; --log)
		if (Up[log][from] && lvl[Up[log][from]] > lvl[to])
		{
			from = Up[log][from];
			Ret += 1 << log;
		}

	return Ret + 1;
}

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

	scanf("%d%d", &N, &M);
	for (int i = 1; i <= M; ++i)
	{
		int a,b;
		scanf("%d%d", &a, &b);
		Adj[a].push_back(b);
		TAdj[b].push_back(a);
	}

	Kosaraju();
	BuildDAG();
	TopologicalSort();
	BuildTree(root);
	BuildLCA();  
		
	scanf("%d",&T);
	for (int i = 1; i <= T; ++i)
	{
		int a,b;
		scanf("%d%d", &a, &b);
		a = comp[a];
		b = comp[b];
		int l = lca(a,b);   
		printf("%d\n", Solve(a,l)); 
	}
}