#include <bits/stdc++.h>
using namespace std;
struct IO {
} io;
IO &operator>>(IO &io, int &n) {
  scanf("%d", &n);
  return io;
}
IO &operator>>(IO &io, unsigned int &n) {
  scanf("%u", &n);
  return io;
}
IO &operator>>(IO &io, long long &n) {
  scanf("%lld", &n);
  return io;
}
IO &operator>>(IO &io, unsigned long long &n) {
  scanf("%llu", &n);
  return io;
}
IO &operator>>(IO &io, double &n) {
  scanf("%lf", &n);
  return io;
}
IO &operator>>(IO &io, long double &n) {
  scanf("%Lf", &n);
  return io;
}
IO &operator>>(IO &io, char *c) {
  scanf("%s", c);
  return io;
}
IO &operator>>(IO &io, string &s) {
  char c;
  s.clear();
  while (isspace(c = getc(stdin))) {
    if (c == -1) return io;
  }
  do {
    s.push_back(c);
  } while (!isspace(c = getc(stdin)));
  if (c != -1) ungetc(c, stdin);
  return io;
}
IO &operator<<(IO &io, const int &n) {
  printf("%d", n);
  return io;
}
IO &operator<<(IO &io, const unsigned int &n) {
  printf("%u", n);
  return io;
}
IO &operator<<(IO &io, const long long &n) {
  printf("%lld", n);
  return io;
}
IO &operator<<(IO &io, const unsigned long long &n) {
  printf("%llu", n);
  return io;
}
IO &operator<<(IO &io, const double &n) {
  printf("%lf", n);
  return io;
}
IO &operator<<(IO &io, const long double &n) {
  printf("%Lf", n);
  return io;
}
IO &operator<<(IO &io, const char c[]) {
  printf("%s", c);
  return io;
}
IO &operator<<(IO &io, const string &s) {
  for (int i = 0; i < (int)(s.size()); ++i) putc(s[i], stdout);
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &p) {
  cout << "(" << p.first << "," << p.second << ")";
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &x) {
  os << "[";
  for (int i = 0; i < (int)(x.size()); ++i) {
    os << x[i];
    if (i != x.size() - 1) os << ",";
  }
  os << "]";
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &x) {
  os << "[";
  for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); ++it) {
    os << *it;
    if (++it != x.end()) os << ",";
    it--;
  }
  os << "]";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const map<S, T> &x) {
  os << "[";
  for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); ++it) {
    os << *it;
    if (++it != x.end()) os << ",";
    it--;
  }
  os << "]";
  return os;
}
void printBit(int b, int k = -1) {
  if (k == -1) {
    int bb = 1, i = 0;
    while (bb) {
      if (b & bb) k = i;
      bb <<= 1;
      i++;
    }
  }
  for (int ct = 0; ct < (int)(k); ++ct) {
    cout << b % 2;
    b >>= 1;
  }
  cout << "\n";
}
struct Edge {
  int src, dst, rev;
  int weight;
  Edge(int src, int dst, int weight = 1, int rev = -1)
      : src(src), dst(dst), weight(weight), rev(rev) {}
};
bool operator<(const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight
         : e.src != f.src     ? e.src < f.src
                              : e.dst < f.dst;
}
void addBiEdge(vector<vector<Edge> > &g, int from, int to, int w = 1) {
  while (g.size() < max(from, to) + 1) g.push_back(vector<Edge>());
  g[from].push_back(Edge(from, to, w, g[to].size()));
  g[to].push_back(Edge(to, from, w, g[from].size() - 1));
}
void addEdge(vector<vector<Edge> > &g, int from, int to, int w = 1) {
  while (g.size() < from + 1) g.push_back(vector<Edge>());
  g[from].push_back(Edge(from, to, w, g[to].size()));
}
vector<int> rev, lev;
int rs = 0;
void visit(const vector<vector<Edge> > &g, int v, int u, vector<Edge> &brdg,
           stack<int> &roots, stack<int> &S, vector<bool> &inS,
           vector<int> &num, int &time) {
  num[v] = ++time;
  S.push(v);
  inS[v] = true;
  roots.push(v);
  for (__typeof((g[v]).begin()) e = (g[v]).begin(); e != (g[v]).end(); ++e) {
    int w = e->dst;
    if (num[w] == 0)
      visit(g, w, v, brdg, roots, S, inS, num, time);
    else if (u != w && inS[w])
      while (num[roots.top()] > num[w]) roots.pop();
  }
  if (v == roots.top()) {
    brdg.push_back(Edge(u, v));
    while (1) {
      int w = S.top();
      S.pop();
      inS[w] = false;
      rev[w] = rs;
      if (v == w) break;
    }
    roots.pop();
    rs++;
  }
}
void bridge(const vector<vector<Edge> > &g, vector<Edge> &brdg) {
  const int n = g.size();
  vector<int> num(n);
  vector<bool> inS(n);
  stack<int> roots, S;
  rev.assign(n, -1);
  rs = 0;
  int time = 0;
  for (int u = 0; u < (int)(n); ++u)
    if (num[u] == 0) {
      visit(g, u, n, brdg, roots, S, inS, num, time);
      brdg.pop_back();
    }
}
struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};
struct Query {
  int u, v, w;
  Query(int u, int v) : u(u), v(v), w(-1) {}
};
void visit(const vector<vector<Edge> > &g, int u, int w, vector<Query> &qs,
           vector<int> &color, vector<int> &ancestor, UnionFind &uf) {
  ancestor[uf.root(u)] = u;
  for (__typeof((g[u]).begin()) e = (g[u]).begin(); e != (g[u]).end(); ++e)
    if (e->dst != w) {
      visit(g, e->dst, u, qs, color, ancestor, uf);
      uf.unionSet(e->src, e->dst);
      ancestor[uf.root(u)] = u;
    }
  color[u] = 1;
  for (__typeof((qs).begin()) q = (qs).begin(); q != (qs).end(); ++q) {
    int w = (q->v == u ? q->u : q->u == u ? q->v : -1);
    if (w >= 0 && color[w]) q->w = ancestor[uf.root(w)];
  }
}
void leastCommonAncestor(const vector<vector<Edge> > &g, int r,
                         vector<Query> &qs) {
  UnionFind uf(g.size());
  vector<int> color(g.size()), ancestor(g.size());
  visit(g, r, -1, qs, color, ancestor, uf);
}
int n, m, k;
vector<vector<Edge> > G, T;
int level = 0;
void dfs(int u, int p) {
  lev[u] = level;
  for (int i = 0; i < (int)(T[u].size()); ++i) {
    int v = T[u][i].dst;
    if (v == p) continue;
    level++;
    dfs(v, u);
    level--;
  }
}
int main() {
  io >> n >> m;
  G.assign(n, vector<Edge>());
  rev.assign(n, 0);
  for (int i = 0; i < (int)(m); ++i) {
    int a, b;
    io >> a >> b;
    a--;
    b--;
    addBiEdge(G, a, b);
  }
  vector<Edge> b;
  bridge(G, b);
  vector<vector<int> > vs(rs);
  for (int u = 0; u < (int)(G.size()); ++u) {
    for (__typeof((G[u]).begin()) e = (G[u]).begin(); e != (G[u]).end(); ++e) {
      int v = e->dst;
      if (rev[u] == rev[v]) continue;
      vs[rev[u]].push_back(rev[v]);
    }
  }
  for (int i = 0; i < (int)(vs.size()); ++i) {
    sort((vs[i]).begin(), (vs[i]).end());
    vs[i].erase(unique((vs[i]).begin(), (vs[i]).end()), vs[i].end());
  }
  T.assign(vs.size(), vector<Edge>());
  for (int u = 0; u < (int)(vs.size()); ++u) {
    for (__typeof((vs[u]).begin()) v = (vs[u]).begin(); v != (vs[u]).end();
         ++v) {
      addEdge(T, u, *v);
    }
  }
  vector<Query> qs;
  io >> k;
  for (int i = 0; i < (int)(k); ++i) {
    int l, r;
    io >> l >> r;
    l--;
    r--;
    l = rev[l], r = rev[r];
    qs.push_back(Query(l, r));
  }
  lev.assign(T.size(), -1);
  dfs(0, -1);
  leastCommonAncestor(T, 0, qs);
  for (int i = 0; i < (int)(k); ++i) {
    cout << lev[qs[i].u] + lev[qs[i].v] - lev[qs[i].w] * 2 << "\n";
  }
  return 0;
}
