Cod sursa(job #3339349)

Utilizator eric.mesterEric Mestereaga eric.mester Data 7 februarie 2026 15:56:36
Problema Obiective Scor 70
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.56 kb
#include <bits/stdc++.h>
#define NMAX 32002
#define LOGMAX 20
#define INF INT_MAX

using namespace std;

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

int N,M,T;
vector <int> G[NMAX],Gt[NMAX],Gctc[NMAX],Gctct[NMAX];
int ctc[NMAX];
vector <int> S;
char vis[NMAX];
int depth[NMAX];
long long sz[NMAX];
int sparse[LOGMAX][NMAX];
int tin[NMAX],tout[NMAX];
int t = 0;

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

void dfs(int node,vector <int> *G,const int c)
{
    vis[node] = 1;
    ctc[node] = c;
    for(int x : G[node]){
        if(!vis[x]) dfs(x, G, c);
    }
    return;
}

bool cmp(int x,int y)
{
    return sz[x] > sz[y];
}

void fix(int node,vector <int> * G)
{
    sz[node] = 1;
    for(int x : G[node]){
        if(sz[x] == 0){
            fix(x, G);
        }
        sz[node] += sz[x];
    }
    sort(G[node].begin(),G[node].end(),cmp);
}

void build1(int node,vector <int> * G, vector <int> * Gt)
{
    tin[node] = ++t;
    vis[node] = 1;
    for(int x : G[node]){
        if(!vis[x]){
            depth[x] = depth[node] + 1;
            sparse[0][x] = node;
            build1(x,G, Gt);
        }
    }
    tout[node] = t;
}

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

int LA(int node,int K)
{
    for(int i=0;i<20;i++){
        if(K & (1<<i)){
            node = sparse[i][node];
        }
    }
    return node;
}

int caut_bin(int x, int y)
{
    int le =0;
    int ri = N;
    int ret = -1;
    while(le <= ri){
        int mid = (le+ri)/2;
        int z = LA(x,mid);
        if(tin[z] <= tin[y] && tout[y] <= tout[z]){
            ret = mid;
            ri = mid-1;
        }else{
            le = mid+1;
        }
    }
    if(ret == -1)exit(88);
    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,S);
    }
    reverse(S.begin(),S.end());
    memset(vis, 0 , sizeof(vis));
    int cnt = 0;
    for(int node : S){
        if(!vis[node]){
            dfs(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]);
                Gctct[ctc[x]].push_back(ctc[node]);
            }
        }
    }
    fix(1, Gctc);
    memset(vis, 0 , sizeof(vis));
    build1(1,Gctc, Gctct);
    memset(vis, 0 , sizeof(vis));
    build2(1,Gctc, Gctct);
    tout[0] = INF;
    for(int node=1;node<=cnt;node++){
        for(int i=1;(1<<i) <=depth[node];i++){
            sparse[i][node] = sparse[i-1][sparse[i-1][node]];
        }
    }
    fin >> T;
    while(T--){
        int x,y;
        fin >> x >> y;
        x = ctc[x];
        y = ctc[y];
        ///de la x la y
        fout << caut_bin(x,y) << "\n";
    }
//    for(int i=1;i<=N;i++){
//        cout << i << " : " << ctc[i] << " " << tin[ctc[i]] << " " << tout[ctc[i]] << "\n";
//    }
//    for(int i=1;i<=cnt;i++){
//        cout << i << " : ";
//        for(int j =0;j<=3;j++){
//            cout << sparse[j][i] << " ";
//        }
//        cout << "\n";
//    }
}