Cod sursa(job #2271271)

Utilizator NOSCOPEPROKENDYMACHEAMACUMVREAU NOSCOPEPROKENDY Data 28 octombrie 2018 12:30:09
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.12 kb
#include <fstream>

#include <vector>

#include <cstring>

#include <algorithm>



using namespace std;



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



const int nmax = 32e3;

const int logmax = 14;

const int inf = 1 << 30;



int n, nrc, rad;

bool viz[nmax + 1], grnenul[nmax + 1];

int comp[nmax + 1];

vector< int > ord, g[ 2 ][nmax + 1];



int h[nmax + 1], link[nmax + 1];

int d[logmax + 1][nmax + 1];

int l[logmax + 1][nmax + 1];



vector< int > gc[nmax + 1];



void dfs_ctc (int nod, int ind) {

    viz[ nod ] = 1;

    if (ind == 1)

        comp[ nod ] = nrc;



    for (auto i : g[ ind ][ nod ]) {

        if (viz[ i ] == 0) {

            dfs_ctc (i, ind);

        }

    }



    if (ind == 0)

        ord.push_back( nod );

}



void ctc () {

    for (int i = 1; i <= n; ++ i) {

        if (viz[ i ] == 0)

            dfs_ctc (i, 0);

    }



    memset(viz, 0, sizeof(viz));

    reverse(ord.begin(), ord.end());



    for (auto i : ord) {

        if (viz[ i ] == 0) {

            ++ nrc;

            dfs_ctc (i, 1);

        }

    }

}



void trage_muchii_ctc () {

    for (int i = 1; i <= n; ++ i) {

        for (auto j : g[ 0 ][ i ]) {

            if (comp[ i ] != comp[ j ]) {

                gc[ comp[ i ] ].push_back(comp[ j ]);

                grnenul[ comp[ j ] ] = 1;

            }

        }

    }



    for (int i = 1; i <= nrc; ++ i) {

        sort(gc[ i ].begin(), gc[ i ].end());

        gc[ i ].erase(unique(gc[ i ].begin(), gc[ i ].end()), gc[ i ].end());



        if (grnenul[ i ] == 0)

            rad = i;

    }

}



void dfs (int nod) {

    viz[ nod ] = 1;



    for (auto i : gc[ nod ]) {

        if (link[ i ] == 0 || h[ link[ i ] ] > h[ nod ]) {

            link[ i ] = nod;

        }

    }



    for (auto i : gc[ nod ]) {

        if (viz[ i ] == 0) {

            d[ 0 ][ i ] = nod;

            h[ i ] = h[ nod ] + 1;



            dfs( i );



            if (link[ nod ] == 0 || h[ link[ nod ] ] > h[ link[ i ] ]) {

                link[ nod ] = link[ i ];

            }

        }

    }

}



void precalc () {

    for (int i = 1; (1 << i) <= nrc; ++ i) {

        for (int j = 1; j <= nrc; ++ j) {

            d[ i ][ j ] = d[i - 1][ d[i - 1][ j ] ];

        }

    }



    for (int i = 1; i <= nrc; ++ i)

        l[ 0 ][ i ] = link[ i ];



    for (int i = 1; (1 << i) <= nrc; ++ i) {

        for (int j = 1; j <= nrc; ++ j) {

            l[ i ][ j ] = l[i - 1][ l[i - 1][ j ] ];

        }

    }

}



int lca_query (int x, int y) {

    if (h[ x ] > h[ y ])

        swap(x, y);



    int dif = h[ y ] - h[ x ];

    for (int i = logmax; i >= 0; -- i) {

        if (dif & (1 << i))

            y = d[ i ][ y ];

    }



    for (int i = logmax; i >= 0; -- i) {

        if (d[ i ][ x ] != d[ i ][ y ]) {

            x = d[ i ][ x ];

            y = d[ i ][ y ];

        }

    }



    if (x != y)

        x = d[ 0 ][ x ];

    return x;

}



int main () {

    int m;

    fin >> n >> m;



    for (int i = 1; i <= m; ++ i) {

        int x, y;

        fin >> x >> y;

        g[ 0 ][ x ].push_back( y );

        g[ 1 ][ y ].push_back( x );

    }



    ctc ();

    trage_muchii_ctc ();



    memset(viz, 0, sizeof(viz));

    dfs( rad );

    precalc ();



    int t;

    fin >> t;



    for (int i = 1; i <= t; ++ i) {

        int x, y;

        fin >> x >> y;



        x = comp[ x ], y = comp[ y ];



        int lim = h[ lca_query(x, y) ];

        int ans = 0;



        for (int j = logmax; j >= 0; -- j) {

            if (h[ l[ j ][ x ] ] > lim) {

                x = l[ j ][ x ];

                ans += (1 << j);

            }

        }



        if (h[ x ] > lim)

            ++ ans;



        fout << ans << "\n";



    }



    fin.close();

    fout.close();

    return 0;

}