#include <bits/stdc++.h>
using namespace std;
int getint() {
  unsigned int c;
  int x = 0;
  while (((c = getchar()) - '0') >= 10) {
    if (c == '-') return -getint();
    if (!~c) exit(0);
  }
  do {
    x = (x << 3) + (x << 1) + (c - '0');
  } while (((c = getchar()) - '0') < 10);
  return x;
}
const int N = 100111;
struct Bridge {
  struct edge {
    int to, rv;
    edge() {}
    edge(int to, int rv) : to(to), rv(rv) {}
  };
  int nv, cnt;
  vector<edge> graph[N];
  int dis[N], low[N], par[N];
  void init(int v = N) {
    nv = v;
    for (v = 0; v < nv; v++) graph[v].clear();
  }
  void add_edge(int u, int v) {
    if (u == v) return;
    int tu = graph[u].size(), tv = graph[v].size();
    graph[u].push_back(edge(v, tv)), graph[v].push_back(edge(u, tu));
  }
  void proc() {
    cnt = 0;
    fill(dis, dis + nv, ~0);
    for (int u = 0; u < nv; u++)
      if (!~dis[u]) dfs(u, -1, -1);
  }
  void dfs(int u, int p, int pe) {
    dis[u] = low[u] = cnt++, par[u] = p;
    for (int i = 0; i < graph[u].size(); i++) {
      int v = graph[u][i].to;
      if (i == pe) continue;
      if (~dis[v]) {
        low[u] = min(low[u], dis[v]);
      } else {
        dfs(v, u, graph[u][i].rv);
        low[u] = min(low[u], low[v]);
      }
    }
  }
  bool is_bridge(int u, int v) {
    if (dis[u] > dis[v]) swap(u, v);
    return (u == par[v] and dis[v] <= low[v]);
  }
};
struct UnionFind {
  vector<int> par;
  void init(int n) { par.assign(n, ~0); }
  int root(int x) { return par[x] < 0 ? x : par[x] = root(par[x]); }
  bool connect(int x, int y) {
    x = root(x), y = root(y);
    if (x == y) return 0;
    if (par[y] < par[x]) swap(x, y);
    par[x] += par[y], par[y] = x;
    return 1;
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int size(int x) { return -par[root(x)]; }
};
int n, m, k;
int us[N], vs[N];
int as[N], bs[N];
Bridge brg;
UnionFind uf;
struct LowestCommonAncestor {
  static const int LOGV = 20;
  static const int V = 100111;
  vector<int> graph[V];
  int par[LOGV][V], dep[V], nv;
  void init(int v) {
    nv = v, memset(par, ~0, sizeof(par));
    for (v = 0; v < nv; v++) graph[v].clear();
  }
  void add_edge(int u, int v) {
    graph[u].push_back(v);
    graph[v].push_back(u);
  }
  void dfs(int u, int p, int d) {
    par[0][u] = p, dep[u] = d;
    for (int i = 0; i < graph[u].size(); i++)
      if (p != graph[u][i]) dfs(graph[u][i], u, d + 1);
  }
  void prepare(int root) {
    dfs(root, ~0, 0);
    for (int k = 0; k + 1 < LOGV; k++)
      for (int v = 0; v < nv; v++) {
        if (!~par[k][v])
          par[k + 1][v] = ~0;
        else
          par[k + 1][v] = par[k][par[k][v]];
      }
  }
  int get(int u, int v) {
    if (dep[u] > dep[v]) swap(u, v);
    for (int k = 0; k < LOGV; k++)
      if (dep[v] - dep[u] >> k & 1) v = par[k][v];
    if (u == v) return u;
    for (int k = LOGV - 1; ~k; --k)
      if (par[k][u] != par[k][v]) u = par[k][u], v = par[k][v];
    return par[0][u];
  }
};
LowestCommonAncestor lca;
int name[N];
int main() {
  int i, j, tcc, tc = 1 << 28;
  for (tcc = 0; tcc < tc; tcc++) {
    n = getint(), m = getint();
    brg.init(n);
    for (i = 0; i < m; i++) {
      us[i] = getint() - 1;
      vs[i] = getint() - 1;
      brg.add_edge(us[i], vs[i]);
    }
    brg.proc();
    k = getint();
    for (i = 0; i < k; i++) {
      as[i] = getint() - 1;
      bs[i] = getint() - 1;
    }
    uf.init(n);
    for (i = 0; i < m; i++)
      if (!brg.is_bridge(us[i], vs[i])) {
        uf.connect(us[i], vs[i]);
      }
    int M = 0;
    for (i = 0; i < n; i++)
      if (uf.root(i) == i) {
        name[i] = M++;
      }
    lca.init(M);
    for (i = 0; i < m; i++)
      if (brg.is_bridge(us[i], vs[i])) {
        int uu = name[uf.root(us[i])];
        int vv = name[uf.root(vs[i])];
        lca.add_edge(uu, vv);
      }
    lca.prepare(0);
    for (i = 0; i < k; i++) {
      int uu = name[uf.root(as[i])];
      int vv = name[uf.root(bs[i])];
      int a = lca.dep[uu];
      int b = lca.dep[vv];
      int c = lca.dep[lca.get(uu, vv)];
      printf("%d\n", a + b - 2 * c);
    }
  }
  return 0;
}
