Cod sursa(job #2100407)

Utilizator popabogdanPopa Bogdan Ioan popabogdan Data 5 ianuarie 2018 16:38:06
Problema Obiective Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.31 kb
#include <bits/stdc++.h>

#define Nmax 32005

using namespace std;

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

int N, M, Q;
vector <int> G[Nmax], Gt[Nmax], newG[Nmax];
int coresp[Nmax];
int S[Nmax], L;
bool vis[Nmax];
int lev[Nmax];
int in[Nmax];
int C;
int T[0][Nmax], kT[16][Nmax];

void topSort(int node)
{
    vis[node] = true;
    for(auto it : G[node])
        if(!vis[it])
            topSort(it);
    S[++L] = node;
}

void getCoresp(int node, int cs)
{
    coresp[node] = cs;
    vis[node] = true;
    for(auto it : Gt[node])
        if(!vis[it])
            getCoresp(it, cs);
}

void getLev(int node)
{
    queue <int> Q;
    Q.push(node);
    lev[node] = 1;
    while(!Q.empty())
    {
        node = Q.front();
        Q.pop();
        for(auto it : newG[node])
        {
            in[it]--;
            if(in[it] == 0 && lev[it] == 0)
                lev[it] = 1 + lev[node], Q.push(it);
        }
    }
}

void getT(int node)
{
    int mi = 1000000000;
    for(auto it : newG[node])
    {
        mi = min(mi, lev[it]);
        if(kT[0][it] == 0)
            kT[0][it] = node;
        else
            if(lev[node] < lev[kT[0][it]])
                kT[0][it] = node;
    }
    for(auto it : newG[node])
    {
        if(lev[it] == mi)
            getT(it), T[0][it] = node;
        if(lev[kT[0][node]] > lev[kT[0][it]])
            kT[0][node] = kT[0][it];
    }
}

int getLca(int x, int y)
{
    if(lev[x] > lev[y])
        swap(x, y);
    int k = lev[y] - lev[x];
    for(int i = 15; i >= 0; i--)
        if(k & (1 << i))
            y = T[i][y];
    if(x == y)
        return x;
    for(int i = 15; i >= 0; i--)
        if(T[i][x] != T[i][y])
    {
        x = T[i][x];
        y = T[i][y];
    }
    return T[0][x];
}

int main()
{
    fin >> N >> M;
    while(M--)
    {
        int x, y;
        fin >> x >> y;
        G[x].push_back(y);
        Gt[y].push_back(x);
    }
    for(int i = 1; i <= N; i++)
        if(!vis[i])
            topSort(i);
    reverse(S + 1, S + N + 1);
    memset(vis, false, sizeof(vis));
    for(int i = 1; i <= N; i++)
        if(!vis[S[i]])
            getCoresp(S[i], ++C);
    for(int i = 1; i <= N; i++)
        for(auto it : G[i])
            if(coresp[i] != coresp[it])
                newG[coresp[i]].push_back(coresp[it]), in[coresp[it]]++;
    memset(vis, false, sizeof(vis));
    int root;
    for(int i = 1; i <= C; i++)
        if(in[i] == 0)
        {
            root = i;
            getLev(i);
            break;
        }
    T[0][root] = kT[0][root] = root;
    lev[root] = 1;
    getT(root);
    for(int i = 1; i <= 15; i++)
        for(int j = 1; j <= N; j++)
            kT[i][j] = kT[i - 1][kT[i - 1][j]], T[i][j] = T[i - 1][T[i - 1][j]];
    for(fin >> Q; Q; Q--)
    {
        int x, y;
        fin >> x >> y;
        x = coresp[x];
        y = coresp[y];
        if(x == y)
            fout << "0\n";
        else
        {
            int z = getLca(x, y);
            int ans = 1;
            for(int i = 15; i >= 0; i--)
                if(lev[kT[i][x]] > lev[z])
            {
                ans += (1 << i);
                x = kT[i][x];
            }
            fout << ans - (x == z) << "\n";
        }
    }
    return 0;
}