Cod sursa(job #2921445)

Utilizator bem.andreiIceman bem.andrei Data 31 august 2022 10:33:11
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.83 kb
#include <bits/stdc++.h>

using namespace std;

ifstream r("obiective.in");
ofstream w("obiective.out");

int n, m, nr, ordsz;
int where[33003], ord[33003], level[33003];
int t[18][33003], up[18][33003];
vector<int> g[33003], gt[33003], edge[33003];
bool used[33003];
void dfs(int node)
{
    used[node] = 1;
    for(auto it : g[node])
    {
        if(used[it]==0)
        {
            dfs(it);
        }
    }
    ord[++ordsz] = node;
}
void dfs2(int node)
{
    where[node] = nr;
    for(auto it : gt[node])
    {
        if(where[it]==0)
        {
            dfs2(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);
        }
    }
}
int lca(int x, int y)
{
    if(level[x] < level[y])
    {
        swap(x, y);
    }
    int up = level[x] - level[y], i;

    for(int i=0; i<=16; i++)
    {
        if(up & (1<<i))
        {
            x = t[i][x];
        }
    }
    if(x == y)
    {
        return x;
    }
    for(int i=16; 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(int i=16; i>=0; i--)
    {
        if(level[up[i][node]] > level[lim]) ans += (1<<i), node = up[i][node];
    }
    return ans + 1;
}
int main()
{
    int x, y;
    r >> n >> m;
    for(int i=1; i<=m; i++)
    {
        r >> x >> y;
        g[x].push_back(y);
        gt[y].push_back(x);
    }

    for(int i=1; i<=n; i++)
    {
        if(used[i]==0)
        {
            dfs(i);
        }
    }

    for(int i=ordsz; i; i--)
    {
        if(where[ord[i]]==0)
        {
            nr++;
            dfs2(ord[i]);
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(auto it : g[i])
        {
            if(where[it] != where[i])
            {
                edge[where[i]].push_back(where[it]);
            }
        }
    }
    for(int i=1; i<=nr; i++)
    {
        sort(edge[i].begin(), edge[i].end());
    }
    dfs3(1);
    for(int i=nr; i; i--)
    {
        up[0][t[0][i]] = min(up[0][t[0][i]], up[0][i]);
    }
    for(int i=1; i<=16; i++)
    {
        for(int 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 q, L;
    r >> q;
    while(q--)
    {
        r >> x >> y;
        x = where[x];
        y = where[y];
        L = lca(x, y);
        w << goo(x, L) << "\n";
    }
    return 0;
}