#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
#define lg 32002
#define pb push_back
int n, m, x, y, ind, s, nrc, i, j, p1, p2, poz[lg], cmp[lg], euler[2 * lg], init[lg], q[131100], cur, rad, grd[lg], teste, test, lca, cnt[lg];
bool fst[lg];
vector<int> v[2][lg], w[lg];
inline bool compare(int a, int b){
return poz[a] > poz[b];
}
void df(int nod){
fst[nod] = 1;
for (int i = 0; i < (int)v[s][nod].size(); i ++)
if (!fst[ v[s][nod][i] ])
df(v[s][nod][i]);
poz[++ ind] = nod;
}
void find(int nod){
fst[nod] = 0; cmp[nod] = nrc;
for (int i = 0; i < (int)w[nod].size(); i ++)
if (fst[ w[nod][i] ])
find(w[nod][i]);
}
void dfs(int nod, int ad){
fst[nod] = 0;
euler[++ cur] = ad; init[nod] = cur; //printf("%d ", nod);
sort(v[1][nod].begin(), v[1][nod].end(), compare);
for (int i = 0; i < (int)v[1][nod].size(); i ++)
if (fst[ v[1][nod][i] ] == 1){
dfs(v[1][nod][i], ad + 1);
euler[++ cur] = ad; //printf("%d ", nod);
}
}
int cstr(int st, int dr, int poz){
if (st == dr)
return q[poz] = euler[st];
int x = (st + dr) / 2;
return q[poz] = min(cstr(st, x, 2 * poz), cstr(x + 1, dr, 2 * poz + 1));
}
int query(int st, int dr, int poz){
if (p1 <= st && dr <= p2)
return q[poz];
if (p1 > dr || p2 < st)
return 0x3f3f3f3f;
int x = (st + dr) / 2;
return min(query(st, x, 2 * poz), query(x + 1, dr, 2 * poz + 1));
}
void new_tree(int nod){
fst[nod] = 1;
for (int i = 0; i < (int)v[1][nod].size(); i ++)
if (!fst[ v[1][nod][i] ]){
new_tree(v[1][nod][i]);
if (euler[ init[ cnt[nod] ] ] < euler[ init[ cnt[ v[1][nod][i] ] ] ] || cnt[nod] == 0)
cnt[nod] = cnt[ v[1][nod][i] ];
}
for (int i = 0; i < (int)w[nod].size(); i ++)
if (euler[ init[ w[nod][i] ] ] < euler[ init[ cnt[nod] ] ] || cnt[nod] == 0)
cnt[nod] = w[nod][i];
if (nod != rad)
v[0][ cnt[nod] ].pb(nod);
}
void inca_un_dfs(int nod){
int i;
fst[nod] = 0;
q[++ ind] = euler[ init[nod] ];
for (i = 0; i < (int)v[1][nod].size(); i ++){
int li = 1, ls = ind, x = ind, gs = -1;
while (li <= ls){
x = (li + ls) / 2;
if (q[x] <= cnt[ v[1][nod][i] ]){
gs = ind - x;
li = x + 1;
}
else
ls = x - 1;
}
//printf("test %d %d\n", nod, cnt[ v[1][nod][i] ]);
grd[ v[1][nod][i] ] = gs;
/*if (nod == 8)
for (int j = 1; j <= ind; j ++)
printf("-> %d\n", q[j]);*/
}
for (i = 0; i < (int)v[0][nod].size(); i ++)
if (fst[ v[0][nod][i] ])
inca_un_dfs(v[0][nod][i]);
ind --;
}
int main()
{
freopen("obiective.in", "rt", stdin);
freopen("obiective.out", "wt", stdout);
scanf("%d%d", &n, &m);
for (i = 1; i <= m; i ++){
scanf("%d%d", &x, &y);
v[0][x].pb(y);
w[y].pb(x);
}
for (i = 1; i <= n; i ++)
if (!fst[i])
df(i);
for (i = n; i; i --)
if (fst[ poz[i] ]){
nrc ++;
find(poz[i]);
}
//for (i = 1; i <= n; i ++)
// printf("%d %d\n", i, cmp[i]);
for (i = 1; i <= n; i ++){
vector<int> schimb;
w[i].swap(schimb);
}
for (i = 1; i <= n; i ++)
for (j = 0; j < (int)v[0][i].size(); j ++){
x = cmp[i], y = cmp[ v[0][i][j] ];
if (x != y){
v[1][x].pb(y);
grd[y] ++;
w[y].pb(x);
}
}
for (i = 1; i <= nrc; i ++)
if (!grd[i]){
rad = i;
break;
}
for (i = 1; i <= n; i ++){
vector<int> schimb;
v[0][i].swap(schimb);
}
ind = 0, s = 1;
df(rad);
//for (i = ind; i; i --)
// printf("%d\n", poz[i]);
//printf(" %d\n", v[1][3][1]);
dfs(rad, 0);
cstr(1, cur, 1);
//for (i = 1; i <= cur; i ++)
// printf("\n-> %d\n", euler[i]);
new_tree(rad);
/*for (i = 1; i <= n; i ++)
for (int j = 0; j < (int)v[0][i].size(); j ++)
printf("%d %d\n", i, v[0][i][j]);*/
for (i = 1; i <= n; i ++){
vector<int> schimb;
v[1][i].swap(schimb);
}
scanf("%d", &teste);
for (test = 1; test <= teste; test ++){
scanf("%d%d", &x, &y);
x = cmp[x], y = cmp[y];
if (x == y){
grd[test] = 0;
continue;
}
p1 = init[x]; p2 = init[y];
if (p1 > p2)
swap(p1, p2);
lca = query(1, cur, 1);
if (lca == euler[ init[x] ]){
grd[test] = 0;
continue;
}
cnt[test] = lca;
v[1][x].pb(test);
}
ind = 0;
inca_un_dfs(rad);
for (i = 1; i <= teste; i ++)
printf("%d\n", grd[i]);
return 0;
}