Cod sursa(job #1950177)

Utilizator Bodo171Bogdan Pop Bodo171 Data 2 aprilie 2017 19:35:45
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.49 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
const int nmax=32005;
vector<int> v[nmax],V[nmax],newv[nmax],lista[nmax],vt[nmax],VP[nmax];
int p[2*nmax],viz[nmax],rad[nmax],c[nmax],tt[nmax],rmq[20][nmax],first[nmax],lev[nmax],lg[nmax],st[nmax],dr[nmax];
int n,m,q,i,k,x,C,nod,t,j,R,unu,doi,a,b,niv,dif,idx;
void dfs(int x)
{
    viz[x]=1;
    for(int i=0;i<v[x].size();i++)
        if(!viz[v[x][i]])
         dfs(v[x][i]);
    k++;p[k]=x;
}
void dfst(int x)
{
    viz[x]=0;c[x]=C;lista[C].push_back(x);
    for(int i=0;i<vt[x].size();i++)
      if(viz[vt[x][i]])
        dfst(vt[x][i]);
}
void build_ctc()
{
    for(x=1;x<=n;x++)
        if(!viz[x])
          dfs(x);
    for(x=n;x>=1;x--)
    {
        nod=p[x];
        if(viz[nod])
            {
                C++;
                dfst(nod);
            }
    }
}
void dfsortop(int x)
{
    viz[x]=1;
    for(int i=0;i<V[x].size();i++)
        if(!viz[V[x][i]])
        dfsortop(V[x][i]);
    k++;p[k]=x;
}
void dfstree(int x)
{
    k++;rmq[0][k]=x;first[x]=k;
    for(int i=0;i<newv[x].size();i++)
    {
        lev[newv[x][i]]=lev[x]+1;
        dfstree(newv[x][i]);
        k++;rmq[0][k]=x;
    }
}
void dfsfreetree(int x)
{
    idx++;st[x]=idx;
    for(int i=0;i<VP[x].size();i++)
        dfsfreetree(VP[x][i]);
    dr[x]=idx;
}
void build_trees()
{
    for(i=1;i<=C;i++)
        rad[i]=1;
    for(i=1;i<=C;i++)
        for(j=0;j<lista[i].size();j++)
             for(k=0;k<v[lista[i][j]].size();k++)
                 if(c[v[lista[i][j]][k]]!=i)
                {
                    V[i].push_back(c[v[lista[i][j]][k]]);
                    rad[c[v[lista[i][j]][k]]]=0;
                }
   k=0;
   for(x=1;x<=C;x++)
     if(!viz[i])
      dfsortop(x);
    for(i=C;i>=1;i--)
    {
        x=p[i];
        for(j=0;j<V[x].size();j++)
            if(!tt[V[x][j]])
                {tt[V[x][j]]=x;}
    }//arborele pe care il folosim cand avem cel putin o strada de reorientat
       for(i=1;i<=C;i++)
        {newv[tt[i]].push_back(i);viz[i]=0;tt[i]=0;}
    for(i=1;i<=C;i++)
        if(rad[i])
         R=i;
    k=0;
    dfstree(R);
      for(i=1;i<=C;i++)
    {
        x=p[i];
        for(j=0;j<V[x].size();j++)
            if(!tt[V[x][j]])
                {tt[V[x][j]]=x;}
    }//arborele folosit cand nu trebuie sa reorientam muchii
    idx=0;//k e folosit la euler la celalt arbore
     for(i=1;i<=C;i++)
        {VP[tt[i]].push_back(i);viz[i]=0;tt[i]=0;}
    dfsfreetree(R);
}
int minlev(int A,int B)
{
    if(lev[A]<lev[B]) return A;
    return B;
}
void build_lca()
{
    for(i=1;(1<<i)<=k;i++)
        for(j=1;j<=k-(1<<i)+1;j++)
         rmq[i][j]=minlev(rmq[i-1][j],rmq[i-1][j+(1<<(i-1))]);
    for(i=2;i<=k;i++)
        lg[i]=lg[i/2]+1;
}
int lca(int A,int B)
{
    unu=first[A];doi=first[B];
    if(unu>doi)
        swap(unu,doi);
    niv=lg[doi-unu+1];
    dif=doi-unu+1-(1<<niv);
    return minlev(rmq[niv][unu],rmq[niv][unu+dif]);
}
int main()
{
    ifstream f("obiective.in");
    ofstream g("obiective.out");
    f>>n>>m;
    for(i=1;i<=m;i++)
    {
        f>>a>>b;
        v[a].push_back(b);
        vt[b].push_back(a);
    }
    build_ctc();
    build_trees();
    build_lca();
    f>>q;
    for(i=1;i<=q;i++)
    {
        f>>a>>b;
        if(st[c[a]]<=st[c[b]]&&st[c[b]]<=dr[c[b]]) g<<"0\n";
        else
        {
        t=lca(c[a],c[b]);
        g<<lev[c[a]]-lev[t]<<'\n';
        }
    }
    return 0;
}