#include <algorithm>
#include <bitset>
#include <fstream>
using namespace std;
const int Nmax = 32005;
int N;
vector<int> G[Nmax], Gt[Nmax];
vector<int> G2[Nmax], Gt2[Nmax];
int Cc[Nmax], Cccnt = 0;
int Snodes[Nmax];
int F[16][Nmax], Father[16][Nmax], Lvl[Nmax];
vector<pair<int, int>> queries;
bitset<Nmax> used;
void Read() {
ifstream fin("obiective.in");
int M;
fin >> N >> M;
while (M--) {
int x, y;
fin >> x >> y;
G[x].push_back(y);
Gt[y].push_back(x);
}
fin >> M;
while (M--) {
int x, y;
fin >> x >> y;
queries.push_back({x, y});
}
fin.close();
}
void Dfs1(const int node) {
used[node] = true;
for (const int p: G[node])
if (!used[p])
Dfs1(p);
Snodes[++Snodes[0]] = node;
}
void Dfs2(const int node) {
used[node] = false;
for (const int p: Gt[node])
if (used[p])
Dfs2(p);
Cc[node] = Cccnt;
}
void getConexComponents() {
for (int i = 1; i <= N; ++i)
if (!used[i])
Dfs1(i);
for (int i = N; i; --i) {
int node = Snodes[i];
if (used[node]) {
++Cccnt;
Dfs2(node);
}
}
for (int i = 1; i <= N; ++i) {
for (int p: G[i]) {
if (Cc[i] != Cc[p]) {
G2[Cc[i]].push_back(Cc[p]);
Gt2[Cc[p]].push_back(Cc[i]);
}
}
}
for (int i = 1; i <= N; ++i) {
sort(G2[i].begin(), G2[i].end());
G2[i].erase(unique(G2[i].begin(), G2[i].end()), G2[i].end());
sort(Gt2[i].begin(), Gt2[i].end());
Gt2[i].erase(unique(Gt2[i].begin(), Gt2[i].end()), Gt2[i].end());
}
}
void Dfs3(const int node) {
used[node] = true;
for (const int p: G2[node])
if (!used[p])
Dfs3(p);
Snodes[++Snodes[0]] = node;
}
void sortConexComponents() {
Snodes[0] = 0;
for (int i = 1; i <= Cccnt; ++i)
if (!used[i])
Dfs3(i);
}
void buildAsc(int F[][Nmax]) {
for (int k = 1; k < 16; ++k)
for (int i = 1; i <= Cccnt; ++i)
F[k][i] = F[k - 1][F[k - 1][i]];
}
void buildTree() {
Lvl[0] = N + 1;
Lvl[N + 1] = -1;
for (int i = Cccnt; i > 0; --i) {
int node = Snodes[i];
F[0][node] = N + 1;
for (const int p: Gt2[node]) {
Lvl[node] = max(Lvl[node], Lvl[p] + 1);
if (Lvl[p] < Lvl[Father[0][node]])
Father[0][node] = p;
if (Lvl[p] > Lvl[F[0][node]])
F[0][node] = p;
}
}
for (int i = 1; i <= Cccnt; ++i) {
int node = Snodes[i];
for (const int p: G2[node]) {
if (Lvl[Father[0][p]] < Lvl[Father[0][node]])
Father[0][node] = Father[0][p];
}
}
F[0][Snodes[Cccnt]] = Father[0][Snodes[Cccnt]] = Snodes[Cccnt];
buildAsc(F);
buildAsc(Father);
}
void Solve() {
getConexComponents();
sortConexComponents();
buildTree();
}
int getUp(int x, int y) {
for (int k = 15; k >= 0; --k)
if (y & (1 << k))
x = F[k][x];
return x;
}
int lca(int x, int y) {
if (Lvl[x] < Lvl[y]) swap(x, y);
x = getUp(x, Lvl[x] - Lvl[y]);
if (x == y) return x;
for (int k = 15; k >= 0; --k)
if (F[k][x] != F[k][y])
x = F[k][x], y = F[k][y];
return F[0][x];
}
int Query(int n1, int n2) {
int l = lca(n1, n2);
if (l == n1) return 0;
int cnt = 1;
for (int k = 15; k >= 0; --k)
if (Lvl[Father[k][n1]] > Lvl[l])
n1 = Father[k][n1], cnt += (1 << k);
return cnt;
}
void Write() {
ofstream fout("obiective.out");
for (const auto& p: queries)
fout << Query(Cc[p.first], Cc[p.second]) << '\n';
fout.close();
}
int main()
{
Read();
Solve();
Write();
}