Cod sursa(job #2344759)

Utilizator Alexa2001Alexa Tudose Alexa2001 Data 15 februarie 2019 16:27:18
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.36 kb
#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)
{
    used[node] = 1;
    for(auto it : v[node])
        if(!used[it]) dfs(it);
    ord[++ordsz] = node;
}
void dfs2(int node)
{
    where[node] = nr;
    for(auto it : vt[node])
        if(!where[it]) dfs2(it);
}

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

    for(i=1; i<=n; ++i)
        for(auto it : v[i])
            if(where[it] != where[i])
                edge[where[i]].push_back(where[it]);

}

void dfs3(int node, int dad = 0)
{
    t[0][node] = dad;
    level[node] = level[dad] + 1;
    up[0][node] = dad;

    for(auto it : edge[node])
        if(!level[it])
            dfs3(it, node);
        else up[0][it] = min(up[0][it], 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;
}