Cod sursa(job #1092364)

Utilizator superman_01Avramescu Cristian superman_01 Data 26 ianuarie 2014 22:19:27
Problema Obiective Scor 60
Compilator cpp Status done
Runda Lista lui wefgef Marime 5.79 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 32768
#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] , t;
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] = ++t;
}
  
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 = G[node].begin() ; it != G[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;
    for ( IT it = G[node].begin() ; it != G[node].end() ; ++it )
        if ( !used[ *it ] )
            DFS_Topo( *it );
    t_out[node] = ++t;
}
  
bool Ancestor ( int x , int y )
{
    return ( t_in[x] <= t_in[y] and t_out[y] <= t_out[x] );
}
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] );
	int copy_N = N;
	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 = 2 ; 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 = GT[i].begin() ; it != GT[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 <= copy_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);
    memset ( used , 0 , sizeof(used));
    t = 0 ,DFS_Topo(1);
    in >> Tests;
    for ( ; Tests > 0 ; --Tests )
    {
        in >> x >> y;
        x = CTC[x] , y = CTC[y];
        
        if ( x == y )
        {
            out << "0\n";
            continue;
        }
		int a = LCA ( x , y );
		if (  a == x )
		{
			out << "0\n";
			continue;
		}
        int log ;
        y = x ;
        for ( log = lg[dep[x]] ; log >= 0 ; --log )
        {
            if ( !Get_High[log][x] ) continue;
            if ( Ancestor ( Get_High[log][x] , a ) ) continue;
            x = Get_High[log][x];
        }
        out << dep[y] - dep[x] + 1 << "\n";
    }
    in.close();
    out.close();
    return 0;           
}