Cod sursa(job #1699134)

Utilizator sucureiSucureiRobert sucurei Data 6 mai 2016 10:51:56
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.51 kb
#include<fstream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<stack>

#define NMAX 32005
#define VEC(G) G[nod][i]

using namespace std;

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

int m,t;
short n,CTC[NMAX],nr,timp[NMAX],low[18][NMAX],TT[18][NMAX],level[NMAX],lg[NMAX];
vector<short> G[NMAX],GT[NMAX];
stack<short> S;
bool use[NMAX];

void read()
{
    fin>>n>>m;
    for(short x,y;m;m--)
    {
        fin>>x>>y;
        G[x].push_back(y);
        GT[y].push_back(x);
    }
    fin>>t;
}

void PM(short nod)
{
    use[nod]=1;
    for(size_t i=0;i<G[nod].size();i++)
        if(!use[VEC(G)])
            PM(VEC(G));
    S.push(nod);
}

void Kosaraju(short nod)
{
    use[nod]=1;
    CTC[nod]=nr;
    for(size_t i=0;i<GT[nod].size();i++)
        if(!use[VEC(GT)])
            Kosaraju(VEC(GT));
}

void edges_CTC()
{
    for(int i=1;i<=n;i++)
        GT[i].clear();
    for(int nod=1;nod<=n;nod++)
        for(size_t i=0;i<G[nod].size();i++)
            if(CTC[nod]!=CTC[VEC(G)])
                GT[CTC[nod]].push_back(CTC[VEC(G)]);
    n=nr;
}

void topo(short nod)
{
    use[nod]=1;
    for(size_t i=0;i<GT[nod].size();i++)
        if(!use[VEC(GT)])
            topo(VEC(GT));
    timp[nod]=++timp[0];
}

bool cmp(const short a,const short b)
{
    return timp[a]>timp[b];
}

void forward(short nod,short tt)
{
    use[nod]=1;
    TT[0][nod]=tt;
    level[nod]=level[tt]+1;
    low[0][nod]=tt;
    for(size_t i=0;i<GT[nod].size();i++)
        if(!use[VEC(GT)])
            forward(VEC(GT),nod);
        else
            if(level[nod]<level[low[0][VEC(GT)]])
                low[0][VEC(GT)]=nod;
}

void lowest(short nod)
{
    use[nod]=1;
    for(size_t i=0;i<GT[nod].size();i++)
        if(!use[VEC(GT)])
        {
            lowest(VEC(GT));
            if(level[low[0][nod]]>level[low[0][VEC(GT)]])
                low[0][nod]=low[0][VEC(GT)];
        }
}

int LCA(short x,short y)
{
    if(level[x]<level[y])
        swap(x,y);
    for(int d=level[x]-level[y];d;x=TT[lg[d]][x],d-=(1<<lg[d]));
    if(x==y)
        return x;
    for(int i=lg[level[y]];i>=0;i--)
        if(TT[i][x] && TT[i][x]!=TT[i][y])
        {
            x=TT[i][x];
            y=TT[i][y];
        }
    return TT[0][x];
}

void ancestors()
{
    for(int i=1;i<=lg[n];i++)
        for(int j=1;j<=n;j++)
        {
            TT[i][j]=TT[i-1][TT[i-1][j]];
            low[i][j]=low[i-1][low[i-1][j]];
        }
}

int main()
{
    read();
    for(int i=2;i<=n;i++)
        lg[i]=lg[i/2]+1;
    for(int i=1;i<=n;i++)
        if(!use[i])
            PM(i);

    memset(use,0,sizeof use);
    for(;!S.empty();S.pop())
        if(!use[S.top()])
        {
            ++nr;
            Kosaraju(S.top());
        }

    edges_CTC();

    memset(use,0,sizeof use);
    topo(1);
    for(int i=1;i<=n;i++)
        sort(GT[i].begin(),GT[i].end(),cmp);

    memset(use,0,sizeof use);
    forward(1,0);
    memset(use,0,sizeof use);
    lowest(1);

    ancestors();

    for(short x,y,L,sol;t;t--)
    {
        fin>>x>>y;
        x=CTC[x];
        y=CTC[y];
        L=LCA(x,y);
        if(x==y || L==x)
        {
            fout<<"0\n";
            continue;
        }
        sol=0;
        for(int step=17;step>=0;step--)
            if(level[low[step][x]]>level[L])
            {
                x=low[step][x];
                sol+=(1<<step);
            }
        fout<<sol+1<<'\n';
    }
    return 0;
}