Pagini recente » Istoria paginii utilizator/silviucostin | Profil M@2Te4i | Monitorul de evaluare | Profil neaR | Cod sursa (job #996345)
Cod sursa(job #996345)
//LCA O(N)
#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[NMAX],TT[NMAX],level[NMAX],nivel[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 niv)
{
use[nod]=1;
nivel[nod]=niv;
for(size_t i=0;i<GT[nod].size();i++)
{
low[VEC(GT)]=nod;
level[VEC(GT)]=niv;
if(!use[VEC(GT)])
{
TT[VEC(GT)]=nod;
forward(VEC(GT),niv+1);
}
}
}
void lowest(short nod)
{
use[nod]=1;
for(size_t i=0;i<GT[nod].size();i++)
if(!use[VEC(GT)])
if(level[VEC(GT)]<level[nod])
{
level[VEC(GT)]=level[nod];
low[VEC(GT)]=low[nod];
}
}
void tree()
{
for(int i=1;i<=n;i++)
GT[i].clear();
for(int i=2;i<=n;i++)
GT[i].push_back(low[i]);
}
int LCA(short x,short y)
{
while(x!=y)
{
if(nivel[x]>nivel[y])
x=TT[x];
if(nivel[x]<nivel[y])
y=TT[y];
}
return x;
}
int main()
{
read();
for(int i=1;i<=n;i++) //Plus-Minus
if(!use[i])
PM(i);
memset(use,0,sizeof use); //Kosaraju
for(;!S.empty();S.pop())
if(!use[S.top()])
{
++nr;
Kosaraju(S.top());
}
edges_CTC(); //Graful CTC
memset(use,0,sizeof use); //Sortarea listelor
topo(1);
memset(use,0,sizeof use);
for(int i=1;i<=n;i++)
sort(GT[i].begin(),GT[i].end(),cmp);
memset(use,0,sizeof use); //Nivelul minim
level[1]=low[1]=1;
forward(1,1);
memset(use,0,sizeof use);
lowest(1);
tree(); //Arborele low
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) // x e stramos a lui y
{
fout<<"0\n";
continue;
}
sol=0;
while(nivel[x]>nivel[L])
{
x=low[x];
sol++;
}
fout<<sol<<'\n';
}
return 0;
}