Cod sursa(job #3303735)

Utilizator Anul2024Anul2024 Anul2024 Data 17 iulie 2025 14:36:32
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.28 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#define dim 32000
using namespace std;
ifstream fin ("obiective.in");
ofstream fout ("obiective.out");
struct mch
{
    int x,y;
};
mch l[2*dim+1];
int n,m,knd,nrctc,nd[dim+1],ctc[dim+1],gr[dim+1],niv[dim+1],t[15][dim+1],nxt[15][dim+1];
bool vis[dim+1];
vector <int> vi[dim+1],vt[dim+1],vn[dim+1],v[dim+1],vnt[dim+1];
queue <int> q;
void read ()
{
    fin>>n>>m;
    for (int i=1; i<=m; i++)
    {
        fin>>l[i].x>>l[i].y;
        vi[l[i].x].push_back (l[i].y);
        vt[l[i].y].push_back (l[i].x);
    }
}
void dfs1 (int nod)
{
    vis[nod]=1;
    for (int i=0; i<(int)vi[nod].size (); i++)
    {
        int vecin=vi[nod][i];
        if (!vis[vecin])
            dfs1 (vecin);
    }
    nd[++knd]=nod;
}
void dfs2 (int nod)
{
    vis[nod]=1;
    ctc[nod]=nrctc;
    for (int i=0; i<(int)vt[nod].size (); i++)
    {
        int vecin=vt[nod][i];
        if (!vis[vecin])
            dfs2 (vecin);
    }
}
void get_ctc ()
{
    for (int i=1; i<=n; i++)
    {
        if (!vis[i])
            dfs1 (i);
    }
    for (int i=1; i<=n; i++)
        vis[i]=0;
    for (int i=n; i>0; i--)
    {
        if (!vis[nd[i]])
        {
            nrctc++;
            dfs2 (nd[i]);
        }
    }
    for (int i=1; i<=n; i++)
        vis[i]=0;
    for (int i=1; i<=m; i++)
    {
        if (ctc[l[i].x]!=ctc[l[i].y])
        {
            vn[ctc[l[i].x]].push_back (ctc[l[i].y]);
            vnt[ctc[l[i].y]].push_back (ctc[l[i].x]);
            gr[ctc[l[i].y]]++;
        }
    }
    n=nrctc;
    for (int i=1; i<=n; i++)
        sort (vn[i].begin (),vn[i].end ());
}
void dfs3 (int nod,int tt,int p)
{
    niv[nod]=p;
    vis[nod]=1;
    t[0][nod]=tt;
    for (int i=0; i<(int)vn[nod].size (); i++)
    {
        int vecin=vn[nod][i];
        if (!vis[vecin])
        {
            v[nod].push_back (vecin);
            dfs3 (vecin,nod,p+1);
        }
    }
}
void dfs4 (int nod)
{
    nxt[0][nod]=nod;
    for (int i=0; i<(int)vnt[nod].size (); i++)
    {
        int vecin=vnt[nod][i];
        if (niv[vecin]<niv[nxt[0][nod]])
            nxt[0][nod]=vecin;
    }
    for (int i=0; i<(int)v[nod].size (); i++)
    {
        int vecin=v[nod][i];
        dfs4 (vecin);
        if (niv[nxt[0][vecin]]<niv[nxt[0][nod]])
            nxt[0][nod]=nxt[0][vecin];
    }
}
void calc ()
{
    for (int p=1; (1<<p)<=n; p++)
    {
        for (int i=1; i<=n; i++)
        {
            t[p][i]=t[p-1][t[p-1][i]];
            nxt[p][i]=nxt[p-1][nxt[p-1][i]];
        }
    }
}
int get_lca (int x,int y)
{
    if (niv[x]<niv[y])
        swap (x,y);
    int dif=niv[x]-niv[y];
    for (int p=14; p>=0; p--)
    {
        if ((dif>>p)&1)
            x=t[p][x];
    }
    for (int p=14; p>=0; p--)
    {
        if (t[p][x]!=t[p][y])
            x=t[p][x],y=t[p][y];
    }
    if (x!=y)
        x=t[0][x];
    return x;
}
int calc (int d,int x)
{
    int sol=0;
    for (int p=14; p>=0; p--)
    {
        if (niv[nxt[p][x]]>d)
        {
            sol+=(1<<p);
            x=nxt[p][x];
        }
    }
    if (niv[x]>d)
        sol++;
    return sol;
}
void solve ()
{
    int q,x,y;
    fin>>q;
    while (q--)
    {
        fin>>x>>y;
        if (ctc[x]==ctc[y])
            fout<<"0\n";
        else
        {
            x=ctc[x];
            y=ctc[y];
            int p=get_lca (x,y);
            fout<<calc (niv[p],x)<<"\n";
        }
    }
}
int main ()
{
    /**
    Facem graful ctc. Noul graf va fi un "arbore" (intr-un nod nu intra doua lanturi - nodurile vor fi pe un lant (res))
    Fiecare nod din lant va fi conectat cu celelalte (au un nod la care se ajunge comun, fara cicli => o sort. top)
    => dintr-un nod pleaca mai multe lanturi.
    Pt a det arborele si niv, sortam listele de muchii pt fiecare nod (primul nod din sort top din lista e un vecin - nu mai e niciun nod mai sus, apoi urmatorul nevizitat (nu e in subarb vecin))
    Din x tb sa vedem nr minim de urcarii <=lca => nxt[0][nod]=niv min din nod (din muchiile spre el), il calculam + din vecini (coboara si apoi urca)
    Facem bl
    **/
    read ();
    get_ctc ();
    dfs3 (1,0,1);
    dfs4 (1);
    calc ();
    solve ();
    return 0;
}