Cod sursa(job #3224998)

Utilizator Botnaru_VictorBotnaru Victor Botnaru_Victor Data 16 aprilie 2024 19:18:40
Problema Obiective Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.58 kb
#include <bits/stdc++.h>
using namespace std;

///----------TOGGLES
#define FIO
#define LONGER
//#define TESTS

///---------

#ifdef LONGER
    #define int long long
#endif // LONGER

#ifdef FIO
    const string fname="obiective";
    ifstream in(fname+".in");
    ofstream out(fname+".out");
    #define cin in
    #define cout out
#endif // FIO

///--------

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

///-------STL++-----
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) x.size()
#define pb(x,y) x.push_back(y)
#define mp(x,y) make_pair(x,y)
#define fr(i,n) for(int i=1;i<=n;i++)
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using pdd = pair<double, double>;
using veci = vector<int>;
using vecp = vector<pii>;
template<typename T> using PQ = priority_queue<T, vector<T>, greater<T> >;

///-----CODE GOES HERE-----

const int maxb = 21;
const int maxn = 32005;

int n,m, q;
int t[maxb][maxn];
int ret[maxb][maxn];


veci g[maxn], rg[maxn];
veci arb[maxn];
veci auxg[maxn];

int vis[maxn];
int col[maxn], ck;
int ord[maxn], invord[maxn], ordk;
int h[maxn];

int besth(int a, int b)
{
    return h[a]<b[h]?a:b;
}

void sortTop(int nod)
{
    vis[nod]=1;
    for(auto e:g[nod])
    {
        if(vis[e]!=1) sortTop(e);
    }
    ord[++ordk]=nod;
}

void colGraf(int nod, int c)
{
    //cerr<<"here "<<nod<<' '<<c<<'\n';
    col[nod]=c;
    vis[nod]=3;
    for(auto e:rg[nod]) if(vis[e]!=3)
    {
        colGraf(e, c);
    }
}

void buildArb(int nod)
{
    //cerr<<"here "<<nod<<'\n';
    vis[nod]=2;
    for(auto e:g[nod])
    {
        if(vis[e]!=2) arb[nod].push_back(e), buildArb(e);
    }
}

void buildDinamici(int nod)
{

    for(int i=1;i<maxb;i++) t[i][nod]=t[i-1][t[i-1][nod]];
    for(auto e:arb[nod])
    {
        t[0][e]=nod;
        h[e]=h[nod]+1;
        buildDinamici(e);
    }
    ret[0][nod]=nod;
    for(auto e:rg[nod]) ret[0][nod]=besth(ret[0][nod], e);
    for(auto e:arb[nod]) ret[0][nod]=besth(ret[0][nod], ret[0][e]);
}

int lca(int a, int b)
{
    if(h[a]<h[b]) swap(a,b);
    for(int step=maxb-1; step>=0;step--)
    {
        if(h[t[step][a]]>=h[b]) a=t[step][a];
    }
    //cerr<<"here! "<<a<<' '<<h[a]<<','<<b<<' '<<h[b]<<'\n';
    if(a==b) return b;
    for(int step=maxb-1;step>=0;step--)
    {
        if(t[step][a]!=t[step][b]) a=t[step][a], b=t[step][b];
    }
    return t[0][a];
}

int retDist(int a, int b)
{
    if(h[a]<=h[b]) return 0;

    int ans=0;
    for(int step=maxb-1; step>=0;step--)
    {
        if(h[ret[step][a]]>h[b]) ans+=(1<<(step)), a=ret[step][a];
    }
    return ans+1;
}

void solve()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        cin>>a>>b;
        pb(g[a],b);
        pb(rg[b],a);
    }

    for(int i=1;i<=n;i++) if(vis[i]!=1) sortTop(i);
    reverse(ord+1, ord+n+1);
    //for(int i=1;i<=n;i++) cerr<<ord[i]<<','<<vis[ord[i]]<<'\n';
    for(int i=1;i<=n;i++) if(vis[ord[i]]!=3) colGraf(ord[i], ++ck);


    for(int i=1;i<=n;i++)
    {
        for(auto e:g[i]) if(col[i]!=col[e])
        {
            auxg[col[i]].push_back(col[e]);
        }
    }
    //for(int i=1;i<=n;i++) cerr<<col[i]<<' ';

    for(int i=1;i<=n;i++) g[i].clear(), rg[i].clear();

    for(int i=1;i<=ck;i++)
    {
        for(auto e:auxg[i])
        {
            g[i].push_back(e);
            rg[e].push_back(i);
        }
    }


    n=ck;

    int root=0;
    for(int i=1;i<=n;i++)
    {
        if(rg[i].size()==0)
        {
            root=i;
            sortTop(i);
            break;
        }
    }
    reverse(ord+1, ord+n+1);

    for(int i=1;i<=n;i++) invord[ord[i]]=i;

    for(int i=1;i<=n;i++) sort(all(g[i]), [&](int a, int b){return invord[a]<invord[b];});

    buildArb(root);
    h[0]=-1;
    buildDinamici(root);

    for(int i=1;i<maxb;i++)
    {
        for(int j=1;j<=n;j++)
        {
            ret[i][j]=ret[i-1][ret[i-1][j]];
        }
    }

    /*for(int i=1;i<=n;i++)
    {
        cout<<h[i]<<' '<<t[0][i]<<' '<<t[1][i]<<'\n';
    }
    cout<<'\n';*/

    cin>>q;
    int a,b;
    for(int i=1;i<=q;i++)
    {
        cin>>a>>b;
        a=col[a];
        b=col[b];
        int c=lca(a,b);
        //cout<<a<<' '<<b<<' '<<c<<'\n';
        cout<<retDist(a,c) +retDist(c,b)<<'\n';
    }



}

///---MAIN FUNC-------

int32_t main()
{
    IOS;
    int t=1;
    #ifdef TESTS
        cin>>t;
    #endif // TESTS
    while(t--)
    {
        solve();
    }
    return 0;
}