Cod sursa(job #2393835)

Utilizator BogdanAlexandruBogdan-Alexandru Dig BogdanAlexandru Data 1 aprilie 2019 09:32:16
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.92 kb
/// By Alexa Tudose (Alexa2001)
/// Just I'm looking, not I'm stealing : )
#include <bits/stdc++.h>

using namespace std;

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

const int Nmax = 33000, lg = 16;

int n, m, nr, ordsz;
int where[Nmax], ord[Nmax], level[Nmax];
int t[lg+2][Nmax], up[lg+2][Nmax];
vector<int> v[Nmax], vt[Nmax], edge[Nmax];
bool used[Nmax];

void dfs(int node)
{
    int i,vecin,t;
    used[node] = 1;
    t=v[node].size();
    for(i=0;i<t;++i)
    {
        vecin=v[node][i];
        if(!used[vecin]) dfs(vecin);
    }
    ord[++ordsz] = node;
}
void dfs2(int node)
{
    int i,vecin,t;
    where[node] = nr;t=vt[node].size();
    for(i=0;i<t;++i)
    {
        vecin=vt[node][i];
        if(!where[vecin]) dfs2(vecin);
    }
}

void init()
{
    int i, x, y;
    fin >> n >> m;
    for(i=1; i<=m; ++i)
    {
        fin >> x >> y;
        v[x].push_back(y);
        vt[y].push_back(x);
    }

    for(i=1; i<=n; ++i)
        if(!used[i]) dfs(i);

    for(i=ordsz; i; --i)
        if(!where[ord[i]])
        {
            ++nr;
            dfs2(ord[i]);
        }
    int t,vecin,j;
    for(i=1; i<=n; ++i)
    {
        t=v[i].size();
        for(j=0;j<t;++j)
        {
            vecin=v[i][j];
            if(where[vecin] != where[i])
                edge[where[i]].push_back(where[vecin]);
        }
    }

}

void dfs3(int node, int dad = 0)
{
    t[0][node] = dad;
    level[node] = level[dad] + 1;
    up[0][node] = dad;
    int t,vecin,j;
    t=edge[node].size();
    for(j=0;j<t;++j)
    {
        vecin=edge[node][j];
        if(!level[vecin])
            dfs3(vecin, node);
        else up[0][vecin] = min(up[0][vecin], node);
    }
}

void precompute()
{
    int i, j;
    for(i=1; i<=nr; ++i) sort(edge[i].begin(), edge[i].end());
    dfs3(1);

    for(i=nr; i; --i) up[0][t[0][i]] = min(up[0][t[0][i]], up[0][i]);

    for(i=1; i<=lg; ++i)
        for(j=1; j<=nr; ++j)
        {
            t[i][j] = t[i-1][t[i-1][j]];
            up[i][j] = up[i-1][up[i-1][j]];
        }
}

int lca(int x, int y)
{
    if(level[x] < level[y]) swap(x, y);
    int up = level[x] - level[y], i;

    for(i=0; i<=lg; ++i)
        if(up & (1<<i)) x = t[i][x];

    if(x == y) return x;

    for(i=lg; i>=0; --i)
        if(t[i][x] != t[i][y])
            x = t[i][x], y = t[i][y];
    return t[0][x];
}

int goo(int node, int lim)
{
    if(node == lim) return 0;

    int i, ans = 0;
    for(i=lg; i>=0; --i)
        if(level[up[i][node]] > level[lim]) ans += (1<<i), node = up[i][node];
    return ans + 1;
}

void solve_queries()
{
    int x, y, q, L;

    fin >> q;
    while(q--)
    {
        fin >> x >> y;
        x = where[x]; y = where[y];
        L = lca(x, y);
        fout << goo(x, L) << '\n';
    }
}

int main()
{
    init();
    precompute();
    solve_queries();
    return 0;
}