Pagini recente » Cod sursa (job #936141) | Cod sursa (job #2051594) | Cod sursa (job #2136196) | Cod sursa (job #1520154) | Cod sursa (job #996484)
Cod sursa(job #996484)
//LCA O(log 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[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++) //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
forward(1,0);
memset(use,0,sizeof use);
lowest(1);
ancestors(); //Stramosii
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;
for(int step=17;step>=0;step--)
if(low[step][x] && level[low[step][x]]>level[L])
{
x=low[step][x];
sol+=(1<<step);
}
fout<<sol+1<<'\n';
}
return 0;
}