Cod sursa(job #996488)

Utilizator raulstoinStoin Raul raulstoin Data 12 septembrie 2013 00:48:31
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.93 kb
#include<fstream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<stack>

#define NMAX 32005
#define VEC(G) G[nod][i]

using namespace std;

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

int m,t;
short n,CTC[NMAX],nr,timp[NMAX],low[18][NMAX],TT[18][NMAX],level[NMAX],lg[NMAX];
vector<short> G[NMAX],GT[NMAX];
stack<short> S;
bool use[NMAX];

void read()
{
	fin>>n>>m;
	for(short x,y;m;m--)
	{
		fin>>x>>y;
		G[x].push_back(y);
		GT[y].push_back(x);
	}
	fin>>t;
}

void PM(short nod)
{
	use[nod]=1;
	for(size_t i=0;i<G[nod].size();i++)
		if(!use[VEC(G)])
			PM(VEC(G));
	S.push(nod);
}

void Kosaraju(short nod)
{
	use[nod]=1;
	CTC[nod]=nr;
	for(size_t i=0;i<GT[nod].size();i++)
		if(!use[VEC(GT)])
			Kosaraju(VEC(GT));
}

void edges_CTC()
{
	for(int i=1;i<=n;i++)
		GT[i].clear();
	for(int nod=1;nod<=n;nod++)
		for(size_t i=0;i<G[nod].size();i++)
			if(CTC[nod]!=CTC[VEC(G)])
				GT[CTC[nod]].push_back(CTC[VEC(G)]);
	n=nr;
}

void topo(short nod)
{
	use[nod]=1;
	for(size_t i=0;i<GT[nod].size();i++)
		if(!use[VEC(GT)])
			topo(VEC(GT));
	timp[nod]=++timp[0];
}

bool cmp(const short a,const short b)
{
	return timp[a]>timp[b];
}

void forward(short nod,short tt)
{
	use[nod]=1;
	TT[0][nod]=tt;
	level[nod]=level[tt]+1;
	low[0][nod]=tt;
	for(size_t i=0;i<GT[nod].size();i++)
		if(!use[VEC(GT)])
			forward(VEC(GT),nod);
		else
			if(level[nod]<level[low[0][VEC(GT)]])
				low[0][VEC(GT)]=nod;
}

void lowest(short nod)
{
	use[nod]=1;
	for(size_t i=0;i<GT[nod].size();i++)
		if(!use[VEC(GT)])
		{
			lowest(VEC(GT));
			if(level[low[0][nod]]>level[low[0][VEC(GT)]])
				low[0][nod]=low[0][VEC(GT)];
		}
}

int LCA(short x,short y)
{
	if(level[x]<level[y])
		swap(x,y);
	for(int d=level[x]-level[y];d;x=TT[lg[d]][x],d-=(1<<lg[d]));
	if(x==y)
		return x;
	for(int i=lg[level[y]];i>=0;i--)
		if(TT[i][x] && TT[i][x]!=TT[i][y])
		{
			x=TT[i][x];
			y=TT[i][y];
		}
	return TT[0][x];
}

void ancestors()
{
	for(int i=1;i<=lg[n];i++)
		for(int j=1;j<=n;j++)
		{
			TT[i][j]=TT[i-1][TT[i-1][j]];
			low[i][j]=low[i-1][low[i-1][j]];
		}
}

int main()
{
	read();
	for(int i=2;i<=n;i++)
		lg[i]=lg[i/2]+1;
	for(int i=1;i<=n;i++)
		if(!use[i])
			PM(i);
	
	memset(use,0,sizeof use);
	for(;!S.empty();S.pop())
		if(!use[S.top()])
		{
			++nr;
			Kosaraju(S.top());
		}
	
	edges_CTC();
	
	memset(use,0,sizeof use);
	topo(1); 
	for(int i=1;i<=n;i++)
		sort(GT[i].begin(),GT[i].end(),cmp);
	
	memset(use,0,sizeof use);
	forward(1,0);
	memset(use,0,sizeof use);
	lowest(1);
	
	ancestors();
	
	for(short x,y,L,sol;t;t--)
	{
		fin>>x>>y;
		x=CTC[x];
		y=CTC[y];
		L=LCA(x,y);
		if(x==y || L==x)
		{
			fout<<"0\n";
			continue;
		}
		sol=0;
		for(int step=17;step>=0;step--)
			if(level[low[step][x]]>level[L])
			{
				x=low[step][x];
				sol+=(1<<step);
			}
		fout<<sol+1<<'\n';
	}
	return 0;
}