Pagini recente » Cod sursa (job #2021823) | Borderou de evaluare (job #1152454) | Cod sursa (job #1950177)
#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;
}