Cod sursa(job #3327482)

Utilizator eric.mesterEric Mestereaga eric.mester Data 4 decembrie 2025 09:50:56
Problema Obiective Scor 15
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.53 kb
#include <bits/stdc++.h>
#define NMAX 32002
#define LOGMAX 16

using namespace std;

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

int N,M,Q;
vector <int> G[NMAX],Gt[NMAX];
vector <int> S;
vector <int> Gctc[NMAX];
int ctc[NMAX];
char vis[NMAX];
int sparse[NMAX][LOGMAX + 2];
int sparse2[NMAX][LOGMAX + 2];
int depth[NMAX];
int T[NMAX];

void sort_top(int node)
{
    vis[node] = 1;
    for(int x : G[node]){
        if(!vis[x]) sort_top(x);
    }
    S.push_back(node);
}

void dfs1(int node,vector <int> *G,int cnt)
{
    ctc[node] = cnt;
    for(int x : G[node]){
        if(ctc[x] == 0) dfs1(x,G,cnt);
    }
    return;
}

void dfs2(int node, vector <int> *G)
{
    vis[node] = 1;
    for(int x : G[node]){
        if(depth[sparse[x][0]] > depth[node]){
            sparse[x][0] = node;
        }
        if(!vis[x]){
            depth[x] = depth[node] + 1;
            T[x] = node;
            dfs2(x,G);
        }
    }
    return;
}

void dfs3(int node, vector <int> *G)
{
    sparse2[node][0] = T[node];
    for(int x : G[node]){
        if(T[x] == node) dfs3(x,G);
    }
    if(depth[sparse[T[node]][0]] > depth[sparse[node][0]]){
        sparse[T[node]][0] = sparse[node][0];
    }
}

int move_up(int node,int steps, int sparse[NMAX][LOGMAX + 2])
{///nu vr sa fac optimizare sa am doar log si nu log^2
    int lg =0;
    while(steps){
        if(steps&1){
            node = sparse[node][lg];
        }
        steps >>=1;
        lg++;
    }
    return node;
}

int __lca(int a,int b)
{
    ///aducem la acceasi adancime
    if(depth[a] > depth[b]){///presupunem ca b ii mai adanc
        swap(a,b);
    }
    b = move_up(b,depth[b] - depth[a], sparse2);
    int le,ri,ret;
    le = 0;
    ri = N;
    ret = N;
    while(le <= ri){///log^2
        int mid = (le+ri)/2;
        int aa = move_up(a,mid,sparse2);
        int ba = move_up(b,mid,sparse2);
        if(aa == ba){
            ret = aa;
            ri = mid-1;
        }else{
            le = mid+1;
        }
    }
    return ret;
}

int main()
{
    fin >> N >> M;
    for(int i=1;i<=M;i++){
        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]) sort_top(i);
    }
    reverse(S.begin(),S.end());
    int cnt = 0;
    for(int node : S){
        if(ctc[node] == 0) dfs1(node,Gt,++cnt);
    }
    for(int node=1;node<=N;node++){
        for(int x: G[node]){
            if(ctc[x] != ctc[node]){
                Gctc[ctc[node]].push_back(ctc[x]);
            }
        }
    }
    memset(vis,0,sizeof(vis));
    depth[0] = INT_MAX;
    dfs2(1, Gctc);
    sparse[1][0] = 1;
    dfs3(1, Gctc);
    for(int i=2;i<=cnt;i++){
        if(T[i]==0) return 88;
    }
    for(int lg = 1;lg <LOGMAX;lg++){
        for(int node = N;node >=1;node--){
            sparse[node][lg] = sparse[sparse[node][lg-1]][lg-1];
            sparse2[node][lg] = sparse2[sparse2[node][lg-1]][lg-1];
        }
    }
//    for(int i=1;i<=N;i++){
//        cout << i << " : " << ctc[i] << "\n";
//    }
    fin >> Q;
    while(Q--){
        int g,m;
        fin >> g >> m;
        int a = ctc[g];
        int b = ctc[m];
        int lca = __lca(a,b);
        int le = 0;
        int ri = N;
        int ans = N;
//        cout << move_up(ctc[5],1,sparse);
        while(le <= ri){
            int mid = (le+ri)/2;
            int x = move_up(a,mid,sparse);
            if(depth[x] <= depth[lca]){
                ans = mid;
                ri = mid - 1;
            }else{
                le = mid +1;
            }
        }
        fout << ans << "\n";
    }
}