Pagini recente » Cod sursa (job #1704827) | Cod sursa (job #2789812) | Cod sursa (job #1771686) | Cod sursa (job #1562278) | Cod sursa (job #663642)
Cod sursa(job #663642)
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#define NMax 100005
#define LogMax 18
using namespace std;
vector <int> G[NMax], GT[NMax];
int N, TSort[NMax], SCC[NMax], Root;
int A[LogMax][NMax], Log2[NMax], Level[NMax], HA[LogMax][NMax];
bool Used[NMax];
inline void DFP (int X)
{
Used[X]=true;
for (unsigned i=0; i<G[X].size (); ++i)
{
int V=G[X][i];
if (!Used[V])
{
DFP (V);
}
}
TSort[++TSort[0]]=X;
}
inline void DFM (int X)
{
SCC[X]=SCC[0];
for (unsigned i=0; i<GT[X].size (); ++i)
{
int V=GT[X][i];
if (SCC[V]==0)
{
DFM (V);
}
}
}
void Kosaraju ()
{
for (int i=1; i<=N; ++i)
{
if (!Used[i])
{
DFP (i);
}
}
for (int i=TSort[0]; i>0; --i)
{
if (SCC[TSort[i]]==0)
{
++SCC[0];
DFM (TSort[i]);
}
}
}
inline void DFT (int X)
{
Used[X]=true;
for (unsigned i=0; i<GT[X].size (); ++i)
{
int V=GT[X][i];
if (!Used[V])
{
DFT (V);
}
}
TSort[X]=++TSort[0];
}
inline bool Compare (int a, int b)
{
return TSort[a]>TSort[b];
}
void BuildNewG ()
{
for (int i=1; i<=N; ++i)
{
GT[i].clear ();
}
memset (Used, 0, sizeof (Used));
for (int X=1; X<=N; ++X)
{
for (unsigned i=0; i<G[X].size (); ++i)
{
int V=G[X][i];
if (SCC[X]!=SCC[V])
{
GT[SCC[X]].push_back (SCC[V]);
Used[SCC[V]]=true;
}
}
}
for (int X=1; X<=SCC[0]; ++X)
{
if (!Used[X])
{
Root=X;
break;
}
}
memset (Used, 0, sizeof (Used));
memset (TSort, 0, sizeof (TSort));
DFT (Root);
for (int X=1; X<=SCC[0]; ++X)
{
sort (GT[X].begin (), GT[X].end (), Compare);
}
}
inline void DFA (int X)
{
for (int i=1; ; ++i)
{
A[i][X]=A[i-1][A[i-1][X]];
if (A[i][X]==0)
{
break;
}
}
for (unsigned i=0; i<GT[X].size (); ++i)
{
int V=GT[X][i];
if (Level[V]==0)
{
A[0][V]=X;
Level[V]=Level[X]+1;
DFA (V);
}
}
}
void BuildAncestor ()
{
for (int i=2; i<=N; ++i)
{
Log2[i]=Log2[i/2]+1;
}
Level[Root]=1;
DFA (Root);
}
inline void DFH (int X)
{
Used[X]=true;
for (unsigned i=0; i<GT[X].size (); ++i)
{
int V=GT[X][i];
if (!Used[V])
{
DFH (V);
if (Level[HA[0][V]]<Level[HA[0][X]])
{
HA[0][X]=HA[0][V];
}
}
}
for (int i=1; ; ++i)
{
HA[i][X]=HA[i-1][HA[i-1][X]];
if (HA[i][X]==0)
{
break;
}
}
}
void BuildHighest ()
{
for (int i=1; i<=SCC[0]; ++i)
{
HA[0][i]=A[0][i];
}
for (int X=1; X<=SCC[0]; ++X)
{
for (unsigned i=0; i<GT[X].size (); ++i)
{
int V=GT[X][i];
if (Level[X]<Level[HA[0][V]])
{
HA[0][V]=X;
}
}
}
memset (Used, 0, sizeof (Used));
DFH (Root);
for (int i=1; i<=Log2[N]; ++i)
{
for (int j=1; j<=SCC[0]; ++j)
{
HA[i][j]=HA[i-1][HA[i-1][j]];
}
}
}
inline int LCA (int X, int Y)
{
for (; Level[X]>Level[Y]; X=A[Log2[Level[X]-Level[Y]]][X]);
for (; Level[X]<Level[Y]; Y=A[Log2[Level[Y]-Level[X]]][Y]);
if (X==Y)
{
return X;
}
for (int Step=Log2[Level[X]]+1; Step>=0; --Step)
{
if (A[Step][X]!=A[Step][Y])
{
X=A[Step][X];
Y=A[Step][Y];
}
}
if (X!=Y)
{
X=A[0][X];
}
return X;
}
void Solve ()
{
Kosaraju ();
BuildNewG ();
BuildAncestor ();
BuildHighest ();
}
void Read ()
{
freopen ("obiective.in", "r", stdin);
int M;
scanf ("%d %d", &N, &M);
for (; M>0; --M)
{
int X, Y;
scanf ("%d %d", &X, &Y);
G[X].push_back (Y);
GT[Y].push_back (X);
}
}
inline int Query (int X, int Y)
{
int Q=0;
for (int Step=Log2[Level[X]]+1; Step>=0; --Step)
{
if (Level[HA[Step][X]]>Level[Y])
{
Q+=(1<<Step);
X=HA[Step][X];
}
}
return Q+1;
}
void Print ()
{
freopen ("obiective.out", "w", stdout);
int M;
scanf ("%d", &M);
for (; M>0; --M)
{
int X, Y;
scanf ("%d %d", &X, &Y);
X=SCC[X], Y=SCC[Y];
int Z=LCA (X, Y);
if (X==Y or X==Z)
{
printf ("0\n");
continue;
}
printf ("%d\n", Query (X, Z));
}
}
int main ()
{
Read ();
Solve ();
Print ();
return 0;
}