Cod sursa(job #3121344)

Utilizator andrei_marciucMarciuc Andrei andrei_marciuc Data 11 aprilie 2023 21:55:15
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.05 kb
#include <fstream>
#include <vector>
#include <stack>
#include <set>
using namespace std;

ifstream fin( "obiective.in" );
ofstream fout( "obiective.out" );
    
const int MAX = 32e3 + 1;
const int MAXLOG = 17;
const int INF = 2e9;

stack<int> srt;
set<int> dag[ MAX ];
vector<int> g[ MAX ];
vector<int> gt[ MAX ];
int rmq[ MAXLOG + 1 ][ 2 * MAX ];
int anc[ MAXLOG + 1 ][ MAX ];
int comptc[ MAX ];
int lg[ 2 * MAX ];
bool seen[ MAX ];
int prim[ MAX ];
int comptc_num;
int euler_num;

void dfs( int node ) {
    seen[ node ] = true;
    for( auto it : g[ node ] )
        if( seen[ it ] == false )
            dfs( it );
    srt.push( node );
}

void dfsR( int node ) {
    seen[ node ] = false;
    comptc[ node ] = comptc_num;
    for( auto it : gt[ node ] )
        if( seen[ it ] )
            dfsR( it );
}

void euler( int node ) {
    seen[ node ] = true;
    prim[ node ] = ++euler_num;
    rmq[ 0 ][ euler_num ] = node;
    for( auto it : dag[ node ] )
        if( seen[ it ] == 0 ) {
            euler( it );
            rmq[ 0 ][ ++euler_num ] = node;
            anc[ 0 ][ node ] = min( anc[ 0 ][ node ], anc[ 0 ][ it ] );
        }
}

int LCA( int u, int v ) {
    if( prim[ u ] > prim[ v ] )
        swap( u, v );
    int aux = lg[ prim[ v ] - prim[ u ] ];
    return min( rmq[ aux ][ prim[ u ] ], rmq[ aux ][ prim[ v ] - ( 1 << aux ) + 1 ] );
}

int main()
{
    ios_base::sync_with_stdio(false);
fin.tie(NULL);
    int n, m, x, y, t, lca, rez;
    for( int i = 2; i <= 2 * MAX; ++i )
            lg[ i ] = lg[ i / 2 ] + 1;

    fin >> n >> m;
    for( int i = 0; i < m; i++ ) {
        fin >> x >> y;
        g[ x ].push_back( y );
        gt[ y ].push_back( x );
    }

    for( int i = 1; i <= n; i++ )
        if( seen[ i ] == false )
            dfs( i );

    while( srt.empty() == 0 ) {
        if( seen[ srt.top() ] ) {
            ++comptc_num;
            dfsR( srt.top()  );
        }
        srt.pop();
    }

    for( int i = 1; i <= n; i++ )
        anc[ 0 ][ i ] = INF;

    for( int i = 1; i <= n; i++ ) {
        x = comptc[ i ];
        for( auto it : g[ i ] )
            if( x != comptc[ it ] ) {
                y = comptc[ it ];
                dag[ x ].insert( y );
                anc[ 0 ][ y ] = min( anc[ 0 ][ y ], x );
            }
    }

    euler( 1 );
    for( int i = 1; i <= lg[ euler_num ]; i++ ) {
        for( int j = 1; j <= comptc_num; j++ )
            anc[ i ][ j ] = anc[ i - 1 ][ anc[ i - 1 ][ j ] ];
        for( int j = 1; j <= euler_num - ( 1 << i ) + 1; j++ )
            rmq[ i ][ j ] = min( rmq[ i - 1 ][ j ], rmq[ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] );
    }

    fin >> t;
    for( int i = 0; i < t; i++ ) {
        fin >> x >> y;
        x = comptc[ x ]; 
        y = comptc[ y ];
        lca = LCA( x, y );
        if( x == lca )
            rez = 0;
        else {
            rez = 1;
            for( int step = lg[ comptc_num ]; step >= 0; --step )
                if( anc[ step ][ x ] > lca ) {
                    rez += ( 1 << step );
                    x = anc[ step ][ x ];
                }
        }
        fout << rez << '\n';
    }
    return 0;
}