Cod sursa(job #2978058)

Utilizator hhhhhhhAndrei Boaca hhhhhhh Data 12 februarie 2023 21:13:13
Problema Obiective Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.94 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("obiective.in");
ofstream fout("obiective.out");
typedef pair<int,int> pii;
int n,m,root;
int comp[32005],nrcomp;
vector<int> st;
pii g[32005];
vector<int> muchii[32005],inv[32005];
int par[32005];
int in[32005],out[32005],dp[21][32005],nivmin[21][32005],niv[32005],timp,sortpoz[32005],grad[32005];
bool use[32005];
void esete(int nod)
{
    use[nod]=1;
    for(int i:muchii[nod])
        if(!use[i])
            esete(i);
    st.push_back(nod);
}
void build(int nod)
{
    use[nod]=1;
    comp[nod]=nrcomp;
    for(int i:muchii[nod])
        if(!use[i])
            build(i);
}
void dfs(int nod)
{
    timp++;
    in[nod]=timp;
    use[nod]=1;
    nivmin[0][nod]=niv[nod];
    dp[0][nod]=par[nod];
    for(int i=1;i<=20;i++)
        dp[i][nod]=dp[i-1][dp[i-1][nod]];
    for(int i:inv[nod])
    {
        nivmin[0][nod]=min(nivmin[0][nod],niv[i]);
        assert(niv[i]!=0);
    }
    for(int i:muchii[nod])
    {
        if(!use[i])
        {
            niv[i]=niv[nod]+1;
            dfs(i);
        }
        nivmin[0][nod]=min(nivmin[0][nod],nivmin[0][i]);
    }
    out[nod]=timp;
}
int goup(int nod,int lg)
{
    for(int i=20;i>=0;i--)
        if((lg>>i)&1)
            nod=dp[i][nod];
    return nod;
}
bool isancestor(int a,int b)
{
    return in[a]<=in[b]&&out[a]>=out[b];
}
int LCA(int a,int b)
{
    if(niv[a]>niv[b])
        swap(a,b);
    if(isancestor(a,b))
        return a;
    for(int i=20;i>=0;i--)
        if(dp[i][a]!=0&&!isancestor(dp[i][a],b))
            a=dp[i][a];
    return par[a];
}
int getrez(int a,int b)
{
    int ans=0;
    if(niv[a]<=niv[b])
        return 0;
    for(int i=20;i>=0;i--)
    {
        int x=nivmin[i][a];
        if(x>niv[b])
        {
            ans+=(1<<i);
            a=goup(a,niv[a]-x);
        }
    }
    return ans+1;
}
bool bypoz(int a,int b)
{
    return sortpoz[a]<sortpoz[b];
}
int main()
{
    ios_base::sync_with_stdio(false);
    fin.tie(0);
    fin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        fin>>a>>b;
        muchii[a].push_back(b);
        g[i]={a,b};
    }
    for(int i=1;i<=n;i++)
        if(!use[i])
            esete(i);
    reverse(st.begin(),st.end());
    for(int i=1;i<=n;i++)
    {
        use[i]=0;
        muchii[i].clear();
    }
    for(int i=1;i<=m;i++)
        muchii[g[i].second].push_back(g[i].first);
    for(int i:st)
        if(!use[i])
        {
            nrcomp++;
            build(i);
        }
    for(int i=1;i<=n;i++)
        muchii[i].clear();
    n=nrcomp;
    for(int i=1;i<=m;i++)
    {
        int a=comp[g[i].first];
        int b=comp[g[i].second];
        if(a!=b)
        {
            muchii[a].push_back(b);
            inv[b].push_back(a);
            grad[b]++;
        }
    }
    queue<int> coada;
    for(int i=1;i<=n;i++)
        if(grad[i]==0)
            coada.push(i);
    int cnt=0;
    while(!coada.empty())
    {
        int nod=coada.front();
        coada.pop();
        cnt++;
        sortpoz[nod]=cnt;
        for(int i:muchii[nod])
        {
            grad[i]--;
            if(grad[i]==0)
                coada.push(i);
        }
    }
    for(int i=1;i<=n;i++)
        sort(muchii[i].begin(),muchii[i].end(),bypoz);
    for(int i=1;i<=n;i++)
    {
        use[i]=0;
        if(inv[i].empty())
        {
            assert(root==0);
            root=i;
        }
    }
    niv[root]=1;
    dfs(root);
    for(int i=1;i<=20;i++)
        for(int j=1;j<=n;j++)
        {
            int nod=j;
            int pozniv=nivmin[i-1][nod];
            int poz=goup(nod,niv[nod]-pozniv);
            nivmin[i][j]=nivmin[i-1][poz];
        }
    int q;
    fin>>q;
    while(q--)
    {
        int a,b;
        fin>>a>>b;
        a=comp[a];
        b=comp[b];
        int lca=LCA(a,b);
        fout<<getrez(a,lca)<<'\n';
    }
    return 0;
}