Cod sursa(job #1950240)

Utilizator Bodo171Bogdan Pop Bodo171 Data 2 aprilie 2017 20:35:07
Problema Obiective Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.19 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],anc[20][nmax],st[nmax],dr[nmax],rev[nmax];
int n,m,q,i,k,x,C,nod,t,j,R,unu,doi,a,b,niv,dif,idx,cost,pu,newn;
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 dfsfreetree(int x)
{
    idx++;st[x]=idx;
    for(int i=0;i<VP[x].size();i++)
        {
            dfsfreetree(VP[x][i]);
            if(rev[anc[0][VP[x][i]]]>rev[anc[0][x]])
             anc[0][x]=anc[0][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[x])
      dfsortop(x);
    for(i=C;i>=1;i--)
    {
        x=p[i];rev[x]=i;
        for(j=0;j<V[x].size();j++)
            if(!anc[0][V[x][j]])
                {anc[0][V[x][j]]=x;}
    }//arborele pe care il folosim cand avem cel putin o strada de reorientat
    //sortare topologica
    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
    //inversul sortarii topologice
    idx=0;
     for(i=1;i<=C;i++)
        {VP[tt[i]].push_back(i);viz[i]=0;}
    dfsfreetree(R);
}
void build_dp()
{
    for(i=1;(1<<i)<=C;i++)
        for(j=1;j<=C;j++)
          anc[i][j]=anc[i-1][anc[i-1][j]];
}
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_dp();
    f>>q;
    for(i=1;i<=q;i++)
    {
        f>>a>>b;
        if(st[c[a]]<=st[c[b]]&&st[c[b]]<=dr[c[a]]) g<<"0\n";
        else
        {
            a=c[a];b=c[b];cost=0;
            for(pu=17;pu>=0;pu--)
            {
                newn=anc[pu][a];
                if(newn!=0&&(!(st[newn]<=st[b]&&st[b]<=dr[newn])))
                {
                    cost+=(1<<pu);
                    a=newn;
                }
            }
            cost++;
            g<<cost<<'\n';
        }
    }
    return 0;
}