// Ce bine era daca stiam si eu componente biconexe
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define PB push_back
const int NMAX = 1 << 15;
const int LOGM = 17;
int N, M, NE, P;
int H[NMAX], T[NMAX], h[NMAX], Pt[NMAX], Gr[NMAX];
int Cod[NMAX], in[NMAX], poz[NMAX];
vector <int> G[NMAX], Gp[NMAX];
int RMQ[LOGM][1 << LOGM];
bool V[NMAX];
void read(void) {
freopen("obiective.in", "rt", stdin);
int i, u, v;
scanf(" %d %d", &N, &M);
for (i = 0; i < M; ++i) {
scanf(" %d %d", &u, &v);
G[u].PB(v);
}
}
int parinte(const int k) {
if (k != Pt[k])
Pt[k] = parinte(Pt[k]);
return Pt[k];
}
void unite(int p1, int p2) {
p1 = parinte(p1);
p2 = parinte(p2);
if (p1 == p2) return;
if (Gr[p1] > Gr[p2])
Pt[p2] = p1;
else
Pt[p1] = p2;
if (Gr[p1] == Gr[p2]) ++Gr[p2];
}
void DFS(int k) {
vector <int> :: iterator it;
// printf("%d\n", k);
V[k] = true;
H[k] = h[k];
T[k] = k;
for (it = G[k].begin(); it != G[k].end(); ++it) {
// printf("fiu %d\n", *it);
if (V[*it] == false) {
h[*it] = h[k] + 1;
DFS(*it);
}
if (H[*it] < H[k])
H[k] = H[*it], T[k] = T[*it];
}
}
void DFS2(int k, int p) {
vector <int> :: iterator it;
V[k] = true;
// printf("united %d %d\n", k, p);
for (it = G[k].begin(); it != G[k].end(); ++it)
if (V[*it] == false) {
if (H[*it] != h[p]) {
Cod[*it] = ++P;
Gp[Cod[p]].PB(Cod[*it]);
++in[Cod[*it]];
DFS2(*it, *it);
} else {
unite(*it, Cod[p]);
DFS2(*it, p);
}
} else if (H[*it] != h[p]) {
++in[Cod[*it]];
Gp[Cod[p]].PB(Cod[*it]);
}
}
void DFS3(int k) {
vector <int> :: iterator it;
// printf("arbore %d\n", k);
V[k] = true;
RMQ[0][++NE] = k;
poz[k] = NE;
for (it = Gp[k].begin(); it != Gp[k].end(); ++it) {
// printf("%d\n", *it);
if (V[*it] == false) {
H[*it] = H[k] + 1;
DFS3(*it);
RMQ[0][++NE] = k;
}
}
}
void make_RMQ(void) {
int i, j, pas, stp, k;
for (i = 1; (1 << i) <= NE; ++i) {
pas = 1 << i; stp = 1 << (i - 1); k = i - 1;
for (j = 1; j + pas <= 1 + NE; ++j) {
if (H[ RMQ[k][j] ] < H[ RMQ[k][j + stp] ])
RMQ[i][j] = RMQ[k][j];
else
RMQ[i][j] = RMQ[k][j + stp];
}
}
}
void solve(void) {
int i, R = 0;
for (i = 1; i <= N; ++i)
Pt[i] = i;
for (i = 1; i <= N; ++i)
if (V[i] == false)
DFS(i);
memset(V, 0x00, sizeof(V));
for (i = 1; i <= N; ++i)
if (V[i] == false) {
Cod[i] = ++P;
DFS2(i, i);
}
for (i = 1; i <= P; ++i)
if (in[i] == 0) {
R = i;
break;
}
memset(V, 0x00, sizeof(V));
H[R] = 0;
DFS3(R);
make_RMQ();
}
int LCA(int u, int v) {
int d, k, p1, p2;
if (poz[u] < poz[v])
p1 = poz[u], p2 = poz[v];
else
p1 = poz[v], p2 = poz[u];
d = p2 - p1 + 1;
for (k = 0; 1 << (k + 1) <= d; ++k);
p2 = p2 - (1 << k) + 1;
if (H[ RMQ[k][p1] ] < H[ RMQ[k][p2] ])
return RMQ[k][p1];
return RMQ[k][p2];
}
void answer(void) {
FILE *fout = fopen("obiective.out", "wt");
int CNT, i, u, v;
scanf(" %d", &CNT);
for (i = 0; i < CNT; ++i) {
scanf(" %d %d", &u, &v);
u = Cod[ parinte(u) ];
v = Cod[ parinte(v) ];
// printf("answer %d %d LCA = %d\n", u, v, LCA(u, v));
fprintf(fout, "%d\n", H[u] - H[ LCA(u, v) ]);
}
fclose(fout);
}
int main(void) {
// printf("%d\n", sizeof(H) + sizeof(T) + sizeof(h) + sizeof(Pt) + sizeof(Gr) + sizeof(Cod) + sizeof(in) + sizeof(poz) + sizeof(G) + sizeof (Gp) + sizeof(RMQ) + sizeof(V));
read();
solve();
answer();
return 0;
}