Cod sursa(job #3225300)

Utilizator raulandreipopRaul-Andrei Pop raulandreipop Data 17 aprilie 2024 12:08:46
Problema Obiective Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.2 kb
#include<iostream>
#include<vector>
#include<functional>
#include<cassert>

using namespace std;
const int NMAX = 32'002;
vector<int> adjDag[NMAX+1] , adjScc[NMAX+1] , adjSccRev[NMAX+1];
vector<int> adjTree[NMAX+1] , adjDagRev[NMAX+1];
int indeg[NMAX+1];
int component[NMAX+1];

int n, m;
int upLca[20][NMAX+1];
int up[20][NMAX+1];
int root = -1;

vector< vector<int> > scc;

void calcScc ()
{
    vector<int> nodes;
    vector<int> viz(n+1 , 0);
    function<void(int)> dfsStiva = [&] (int nod) -> void {
        nodes.push_back(nod);
        viz[nod] = 1;
        
        for (auto &to : adjScc[nod]) {
            if (!viz[to]) {
                dfsStiva(to);
            }
        }
    };

    function<void(int)> dfsSCC = [&] (int nod) -> void {
        scc.back().push_back(nod);
        viz[nod] = 1;
        component[nod] = scc.size()-1;
        for (auto &to : adjSccRev[nod]) {
            if (!viz[to]) {
                dfsSCC(to);
            }
        }
    };

    for (int i = 1; i <= n; i++)
    {
        if (!viz[i]) {
            dfsStiva(i);
        }
    }

    viz.clear();
    viz.resize(n+1 , 0);
    for (int i = 1; i <= n; i++)
    {
        if (!viz[i])
        {
            scc.push_back({});
            dfsSCC(i);
        }
    }

    for (int comp = 0; comp < scc.size(); comp++)
    {
        for (auto &nod : scc[comp])
        {
            for (auto &to : adjScc[nod])
            {
                // cout << component[nod]
                if (component[nod] != component[to])
                {
                    adjDag[comp].push_back(component[to]);
                    adjDagRev[component[to]].push_back(comp);
                    indeg[component[to]]++;
                }
            }
        }
    }

    
    for (int c = 0; c < scc.size(); c++)
    {
        
        if (indeg[c] == 0) root = c;
    }

    assert(root != -1);

    return;
}

int depth[NMAX+1];

void calcTree ()
{
    function<void(int)> dfs = [&] (int nod) -> void {
        up[0][nod] = nod;

        for (auto &to : adjDag[nod])
        {
            if (depth[to] < depth[nod]+1) {
                depth[to] = depth[nod]+1;
                upLca[0][to] = nod;
                dfs(to);
                if (depth[up[0][to]] < depth[up[0][nod]])
                {
                    up[0][nod] = up[0][to];
                }
            }
        }
        for (auto &to : adjDagRev[nod])
        {
            if (depth[to] < depth[up[0][nod]])
            {
                up[0][nod] = to;
            }
        }
    };

    depth[root] = 1;
    dfs(root);
    up[0][root] = n+1;
    
    for (int b = 0; b < 16; b++) up[b][n+1] = n+1;

    for (int b = 1; b < 16; b++)
    {
        for (int i = 0; i < scc.size(); i++)
        {
            upLca[b][i] = upLca[b-1][upLca[b-1][i]];
            up[b][i] = up[b-1][up[b-1][i]];
        }
    }
}

int lca (int x , int y)
{
    if (depth[x] < depth[y]) swap(x , y);
    int d = depth[x] - depth[y];
    for (int b = 15; b >= 0; b--)
    {
        if ((1 << b) & d)
        {
            x = upLca[b][x];
        }
    }
    if (x == y) return y;
    else {
        for (int b = 15; b >= 0; b--)
        {
            if (upLca[b][x] != upLca[b][y]) {
                x = upLca[b][x];
                y = upLca[b][y];
            }
        }
        return upLca[0][y];
    }

}

int main ()
{
    freopen("obiective.in" , "r" , stdin);
    freopen("obiective.out" , "w" , stdout);
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int x, y; cin >> x >> y;
        adjScc[x].push_back(y);
        adjSccRev[y].push_back(x);
    }

    calcScc();
    calcTree();

    int t; cin >> t;
    while (t--)
    {
        int x, y; cin >> x >> y;
        x = component[x] , y = component[y];
        int _lca = lca(x , y);
        int cost = 0;
        // cout << "!" << _lca << '\n';

        for (int b = 15; b >= 0; b--)
        {
            if (depth[up[b][x]] >= depth[_lca]) {
                cost |= (1 << b);
                x = up[b][x];
            }
        }
        cout << cost << '\n';
    }

    return 0;
}