//bah buru ai dat si tu un tractor, sa mor io... da e marfa ideea ;)
//sigur busesc problema, ca nah.. prea multe linii :P
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define sz size()
#define pb push_back
#define inf 1000000000
#define Nmax 32005
int n, m;
vector<int> vec[Nmax], vec2[Nmax];
vector<int> vc[Nmax], vc2[Nmax];
char viz[Nmax];
int list[Nmax], nlist;
int comp[Nmax], nrc;
int place[Nmax];
int level[Nmax];
int lim = 15;
int c[Nmax][16];
int start[Nmax];
int v[200000], nrv;
int seg[200000];
void readdata()
{
freopen("obiective.in", "r", stdin);
freopen("obiective.out", "w", stdout);
int i, a, b;
scanf("%d %d", &n, &m);
for (i = 1; i <= m; ++i)
{
scanf("%d %d", &a, &b);
vec[a].pb(b);
vec2[b].pb(a);
}
}
void df1(int k)
{
int i, nod;
viz[k] = 1;
for (i = 0; i < vec[k].sz; ++i)
{
nod = vec[k][i];
if (!viz[nod]) df1(nod);
}
list[++nlist] = k;
}
void df2(int k)
{
int i, nod;
viz[k] = 1;
comp[k] = nrc;
for (i = 0; i < vec2[k].sz; ++i)
{
nod = vec2[k][i];
if (!viz[nod]) df2(nod);
}
}
void df3(int k)
{
int i, nod;
viz[k] = 1;
for (i = 0; i < vc[k].sz; ++i)
{
nod = vc[k][i];
if (!viz[nod]) df3(nod);
}
list[++nlist] = k;
}
inline int cmp(int a, int b)
{ return place[a] < place[b]; }
void df4(int k)
{
int i, nod, j;
viz[k] = 1;
v[++nrv] = k;
start[k] = nrv;
for (i = 0; i < vc[k].sz; ++i)
{
nod = vc[k][i];
if (!viz[nod])
{
level[nod] = level[k]+1;
df4(nod);
v[++nrv] = k;
}
}
}
void build(int poz, int st, int dr)
{
if (st == dr)
{
seg[poz] = v[st];
return;
}
int m = (st+dr)/2, p1 = poz*2, p2 = poz*2+1;
build(p1, st, m);
build(p2, m+1, dr);
if (level[ seg[p1] ] < level[ seg[p2] ]) seg[poz] = seg[p1];
else seg[poz] = seg[p2];
}
int interog(int poz, int st, int dr, int a, int b)
{
if (a <= st && dr <= b) return seg[poz];
int m = (st+dr)/2, p1 = poz*2, p2 = poz*2+1, best = 0, val;
if (a <= m) best = interog(p1, st, m, a, b);
if (b > m)
{
val = interog(p2, m+1, dr, a, b);
if (level[val] < level[best]) best = val;
}
return best;
}
void solve()
{
int i, j, nod, nod2;
//afla componentele tare conexe
for (i = 1; i <= n; ++i)
if (!viz[i]) df1(i);
memset(viz, 0, sizeof(viz));
for (i = nlist; i; --i)
if (!viz[ list[i] ])
{
++nrc;
df2(list[i]);
}
//determina graful comprimat
for (i = 1; i <= n; ++i)
for (j = 0; j < vec[i].sz; ++j)
if (comp[i] != comp[ vec[i][j] ])
vc[ comp[i] ].pb( comp[ vec[i][j] ] );
for (i = 1; i <= nrc; ++i)
{
sort(vc[i].begin(), vc[i].end());
vc[i].resize( unique(vc[i].begin(), vc[i].end()) - vc[i].begin());
}
//sorteaza lexicografic noul graf
memset(viz, 0, sizeof(viz));
nlist = 0;
for (i = 1; i <= nrc; ++i)
if (!viz[i]) df3(i);
//LCA stuff
for (i = 1; i <= nrc; ++i)
place[ list[i] ] = i;
for (i = 1; i <= nrc; ++i)
sort(vc[i].rbegin(), vc[i].rend(), cmp);
for (i = 1; i <= nrc; ++i)
for (j = 0; j < vc[i].sz; ++j)
{
nod = vc[i][j];
vc2[nod].pb(i);
}
memset(viz, 0, sizeof(viz));
level[0] = inf;
df4(list[nrc]);
build(1, 1, nrv);
//construieste matrice
for (i = 1; i <= nrc; ++i)
{
nod = list[i];
c[nod][0] = nod;
for (j = 0; j < vc[nod].sz; ++j)
{
nod2 = vc[nod][j];
if (level[ c[nod2][0] ] < level[ c[nod][0] ])
c[nod][0] = c[nod2][0];
}
for (j = 0; j < vc2[nod].sz; ++j)
{
nod2 = vc2[nod][j];
if (level[nod2] < level[ c[nod][0] ])
c[nod][0] = nod2;
}
}
for (j = 1; j <= lim; ++j)
for (i = 1; i <= nrc; ++i)
c[i][j] = c[ c[i][j-1] ][ j-1 ];
}
int solution(int a, int lev)
{
int ret = 0, i, j;
for (j = lim; j >= 0; --j)
if (level[ c[a][j] ] > lev)
{
a = c[a][j];
ret += (1 << j);
}
if (level[a] > lev) ++ret;
return ret;
}
void writedata()
{
int t, a, b, val;
int v1, v2;
for (scanf("%d", &t); t; --t)
{
scanf("%d %d", &a, &b);
a = comp[a], b = comp[b];
v1 = start[a], v2 = start[b];
if (v1 > v2) v1 ^= v2 ^= v1 ^= v2;
val = interog(1, 1, nrv, v1, v2);
printf("%d\n", solution(a, level[val]));
}
}
int main()
{
readdata();
solve();
writedata();
return 0;
}