Cod sursa(job #1090991)

Utilizator superman_01Avramescu Cristian superman_01 Data 23 ianuarie 2014 13:51:39
Problema Obiective Scor 5
Compilator cpp Status done
Runda Lista lui wefgef Marime 4.61 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>

#define get_max(a,b) ((a)>(b)?(a):(b))
#define get_min(a,b) ((a)<(b)?(a):(b))
#define NMAX_SIZE 32005
#define MMAX_SIZE 64005
#define TMAX_SIZE 100005

using namespace std;


typedef vector < int > ::iterator IT ; 

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

vector < int > G[NMAX_SIZE] , GT[NMAX_SIZE] ;
stack < int > S ;
bool used[NMAX_SIZE];
int t_in[NMAX_SIZE] , t_out[NMAX_SIZE];
int N ,M , ctc , Tests, CTC[NMAX_SIZE] , Time[NMAX_SIZE] , lg[NMAX_SIZE] , level[NMAX_SIZE] , up[18][NMAX_SIZE], Highest[NMAX_SIZE]	;
int Get_High[18][NMAX_SIZE] , dep[NMAX_SIZE];
void DFM ( int node )
{
	used[node] = true ;
	for ( IT it = G[node].begin() ; it != G[node].end() ; ++it )
		if ( !used[*it] )
			DFM ( *it );
	S.push(node);
}

void DFP ( int node )
{
	used[node] = true;
	for ( IT it = GT[node].begin() ; it != GT[node].end () ; ++it )
		if ( !used[*it] )
			DFP( *it );
	CTC[node] = ctc;
}

void KosarajuAlgorithm ( void )
{
	int i , j , node;
	for ( i = 1 ; i <= N ; ++i )
		if ( !used[i] )
			DFM(i) ;
	memset ( used , 0 , sizeof (used) );
	for ( ; S.size(); )
	{
		node = S.top();
		if ( !used[node] )
		{
			++ctc;
			DFP ( node );
		}
		S.pop();
	}
}

void TopologicalSort ( int node )
{
	used[node] = true ;
	for ( IT it = GT[node].begin() ; it != GT[node].end() ; ++it )
		if ( !used[*it] )
			TopologicalSort ( *it );
	Time[node] = ++Time[0];
}

bool cmp ( int a , int b ) { return Time[a] > Time[b] ;}

void CreateFather ( int node )
{
	int i , j , x;
	used[node] = true ;
	for ( i = 0 ; up[i][up[i][node]] ; ++i )
	up[i+1][node] = up[i][up[i][node]];
	for ( IT it = GT[node].begin() ; it != GT[node].end() ; ++it )
		if ( !used[ x = *it ] )
		{
			up[0][x] = node;
			level[x] = level[node] + 1 ;
			CreateFather ( x );
		}
}


void DFS_Prop ( int node )
{
	int x ;
	used[node] = true ;
	for ( IT it = GT[node].begin() ; it != GT[node].end(); ++it )
		if ( ! used [ x = *it ] )
	{
		DFS_Prop ( x );
		if ( level [ Highest[x] ]  < level [ Highest[node] ] )
			Highest[node] = Highest[x];
	}
}

void DFS_GH ( int node )
{

	
	int i , j , x;
	used[node] = true ;
	for ( i = 0 ; Get_High[i][Get_High[i][node]] ; ++i )
	Get_High[i+1][node] = Get_High[i][Get_High[i][node]];
	for ( IT it = GT[node].begin() ; it != GT[node].end() ; ++it )
		if ( !used[ x = *it ] )
		{
			Get_High[0][x] = node;
			dep[x] = dep[node] + 1 ;
			DFS_GH ( x );
		}
 	
}

int LCA ( int x , int y)
{
	int i , j ;
	for ( ; level[x] > level[y] ; x = up[lg[level[x]-level[y]]][x]);
	for ( ; level[y] > level[x] ; y = up[lg[level[y]-level[x]]][y]);
	if ( x == y )
		return x;
	int log ;
	for ( log = lg[level[x]]; log >= 0 ; --log )
		if ( up[log][x] != up[log][y] )
		{
			x = up[log][x] ;
			y = up[log][y];
		}
	if( x != y ) x = up[0][x];
	return x;
}
void DFS_Topo ( int node )
{
	used[node] = true;
	t_in[node] = ++t_in[0];
	for ( IT it = G[node].begin() ; it != G[node].end() ; ++it )
		if ( !used[ *it ] )
			DFS_Topo( *it );
	t_out[node] = ++t_in[0];
}
int main ( void )
{
	int i , j , x  , y , node;
	in >> N >> M ;
	for ( i = 1 ; i <= M ; ++i )
	{	
		in >> x >> y ;
		G[x].push_back(y);
		GT[y].push_back(x);
	}
	KosarajuAlgorithm();
	for ( i = 1 ; i <= N ; ++i )
		GT[i].clear();
	for ( i = 1 ; i <= N ; ++i )
		for ( IT it = G[i].begin() ; it != G[i].end() ; ++it )
			if ( CTC[i] != CTC[*it] )
				GT[CTC[i]].push_back( CTC[*it] );
	N = ctc;
	memset ( used , 0 , sizeof(used) );
	TopologicalSort( 1  );
	for ( i = 1 ; i <= N ; ++i )
		sort ( GT[i].begin () ,GT[i].end() , cmp );
	for ( i = 1 ; i <= NMAX_SIZE ; ++i )
	   lg[i] = lg[i/2] + 1 ;
	memset ( used , 0 , sizeof(used) );
	CreateFather( 1  );
	for ( i = 1 ; i <= N ; ++i )
		Highest[i] = up[0][i];
	for ( i = 1 ; i <= N ; ++i )
		for ( IT it = G[i].begin() ; it != G[i].end() ; ++it )
			if ( up[0][*it] != i )
			{
				if ( level[i] < level[Highest[*it] ] )
					Highest[ *it ] = i;
			}
	memset ( used , 0 , sizeof(used));
	DFS_Prop( 1 );
	for ( i = 1 ; i <= N ; ++i )
		G[i].clear();
	for ( i = 1 ; i <= N ; ++i )
		if ( Highest[i] )
			G[Highest[i]].push_back(i);
	memset ( used , 0 , sizeof(used));
	DFS_GH(1);
	DFS_Topo(1);
	in >> Tests;
	for ( ; Tests > 0 ; --Tests )
	{
		in >> x >> y;
		x = CTC[x] , y = CTC[y];
		int a = LCA ( x , y );
		if ( x == y or a == x )
		{
			out << "0\n";
			continue;
		}
		int log ;
		out << min ( dep[x] , dep[y] ) - dep[a] + 1 << "\n";
	}
	in.close();
	out.close();
	return 0;			
}