Cod sursa(job #2147914)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 1 martie 2018 11:24:08
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.6 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 (viz[ i ] == 0) {
            d[ 0 ][ i ] = nod;
            h[ i ] = h[ nod ] + 1;
            link[ i ] = nod;

            dfs( i );

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

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;
}