Cod sursa(job #2983631)

Utilizator pielevladutPiele Vladut Stefan pielevladut Data 22 februarie 2023 18:06:54
Problema Obiective Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.77 kb
#include <bits/stdc++.h>

using namespace std;

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

const int nmax = 32000;
const int LOG = 15;

int n, m, t;
bool visited[nmax + 5];
vector<int> g[nmax + 5];
pair<int, int> muchii[nmax + 5];
stack<int> sortTop;
int pozSortTop[nmax + 5];
int cntSortTop;
int grad[nmax + 5];
int nivel[nmax + 5];
int idxCtc[nmax + 5];
int cntCtc;
int stramosi[nmax + 5][LOG + 1];
int in[nmax + 5], out[nmax + 5], timp;

void dfs1(int fiu)
{
    visited[fiu] = true;
    for(auto it : g[fiu])
    {
        if(visited[it] == true)
        {
            continue;
        }
        dfs1(it);
    }
    sortTop.push(fiu);
}

void dfs2(int fiu)
{
    visited[fiu] = true;
    idxCtc[fiu] = cntCtc;
    for(auto it : g[fiu])
    {
        if(visited[it] == true)
        {
            continue;
        }
        dfs2(it);
    }
}

bool bypoz(int a, int b)
{
    return pozSortTop[a] < pozSortTop[b];
}

void dfs3(int fiu)
{
    timp++;
    in[fiu] = timp;
    visited[fiu] = true;
    for(int i = 1; i <= LOG; i ++)
    {
        stramosi[fiu][i] = stramosi[stramosi[fiu][i - 1]][i - 1];
    }
    for(auto it : g[fiu])
    {
        if(visited[it] == true)
        {
            continue;
        }
        nivel[it] = 1 + nivel[fiu];
        stramosi[it][0] = fiu;
        dfs3(it);
    }
    out[fiu] = timp;
}

bool eStramos(int x, int y)
{
    return in[x] <= in[y] && out[x] >= out[y];
}

int Lca(int x, int y)
{
    if(eStramos(x, y) == true)
    {
        return 0;
    }
    int ans = 1;
    for(int i = LOG; i >= 0; i --)
    {
        if(eStramos(stramosi[x][i], y) == false && stramosi[x][i] != 0)
        {
            ans += (1 << i);
            x = stramosi[x][i];
        }
    }
    return ans;
}

int main()
{
    fin >> n >> m;
    for(int i = 1; i <= m; i ++)
    {
        int x, y;
        fin >> x >> y;
        muchii[i] = {x, y};
        g[x].push_back(y);
    }
    for(int i = 1; i <= n; i ++)
    {
        if(!visited[i])
        {
            dfs1(i);
        }
    }
    for(int i = 1; i <= n; i ++)
    {
        g[i].clear();
        visited[i] = false;
    }
    for(int i = 1; i <= m; i ++)
    {
        g[muchii[i].second].push_back(muchii[i].first);
    }
    while(!sortTop.empty())
    {
        int nod = sortTop.top();
        sortTop.pop();
        if(!visited[nod])
        {
            cntCtc++;
            dfs2(nod);
        }
    }
    for(int i = 1; i <= n; i ++)
    {
        g[i].clear();
    }
    for(int i = 1; i <= m; i ++)
    {
        int x = idxCtc[muchii[i].first];
        int y = idxCtc[muchii[i].second];
        if(x != y)
        {
            g[x].push_back(y);
            grad[y]++;
        }
    }
    n = cntCtc;
    int root = 0;
    for(int i = 1; i <= n; i ++)
    {
        if(grad[i] == 0)
        {
            root = i;
        }
    }
    queue<int> coada;
    coada.push(root);
    while(!coada.empty())
    {
        int nod = coada.front();
        coada.pop();
        cntSortTop++;
        pozSortTop[nod] = cntSortTop;
        for(auto it : g[nod])
        {
            grad[it]--;
            if(grad[it] == 0)
            {
                coada.push(it);
            }
        }
    }
    for(int i = 1; i <= n; i ++)
    {
        visited[i] = false;
        //sort(g[i].begin(), g[i].end(), bypoz);
    }
    nivel[root] = 1;
    dfs3(root);
    fin >> t;
    while(t--)
    {
        int x, y;
        fin >> x >> y;
        x = idxCtc[x];
        y = idxCtc[y];
        if(x == y)
        {
            fout << 0 << '\n';
        }
        else
        {
            fout << Lca(x, y) << '\n';
        }
    }
    /// ? :>:>:>
}