// 
// Strongly Connected Component Comparison
//
// Description:
// 
//   Use Gabow (fast and memory efficient)
//
// g++ -std=c++17 -O3 -fmax-errors=1 -fsanitize=undefined
#include <bits/stdc++.h>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(s) if (!(s)) { cout << __LINE__ << " " << #s << endl; exit(-1); }


// === tick a time ===
#include <ctime>
double tick() {
  static clock_t oldtick;
  clock_t newtick = clock();
  double diff = 1.0*(newtick - oldtick) / CLOCKS_PER_SEC;
  oldtick = newtick;
  return diff;
}

struct Graph {
  int n;
  vector<vector<int>> adj;
  Graph(int n) : n(n), adj(n) { }
  void addEdge(int u, int v) {
    adj[u].push_back(v);
  }
};

// scc.n is the number of components
// there are no edges (i, j) with i < j.
struct StrongConnectedComponents : Graph {
  vector<int> index;         // index[u] is the component in the contracted graph
  vector<vector<int>> block; // u in block[k] <=> index[u] = k
  StrongConnectedComponents(const Graph &g) : Graph(0) {
    index.assign(g.n, -1);
    vector<int> cur(g.n), num(g.n), snum, path;
    for (int s = 0, time = 0; s < g.n; ++s) {
      if (num[s]) continue;
      vector<int> stack = {s};
      while (!stack.empty()) {
        int u = stack.back();
        if (cur[u] == 0) {
          num[u] = ++time; 
          snum.push_back(num[u]);
          path.push_back(u);
        }
        if (cur[u] < g.adj[u].size()) {
          int v = g.adj[u][cur[u]++];
          if (!num[v]) stack.push_back(v);
          else if (index[v] == -1) 
            while (num[v] < snum.back()) snum.pop_back();
        } else {
          if (num[u] == snum.back()) {
            snum.pop_back();
            while (1) {
              int v = path.back(); path.pop_back();
              index[v] = n;
              if (u == v) break;
            }
            ++n;
          }
          stack.pop_back();
        }
      }
    }
    adj.resize(n); // contains many self-loops
    block.resize(n);
    for (int u = 0; u < g.n; ++u) {
      block[index[u]].push_back(u);
      for (int v: g.adj[u]) {
        addEdge(index[u], index[v]); 
      }
    }
  }
};

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  for (int i = 0; i < v.size(); os << v[i++]) 
    if (i > 0) os << " ";
  os << "]";
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<vector<T>> &v) {
  os << "[";
  for (int i = 0; i < v.size(); os << v[i++]) 
    if (i > 0) os << endl << " ";
  os << "]";
  return os;
}

void test() {
  srand(time(0));
  int n = 1000000, m = 4*n;
  Graph g(n);

  for (int i = 0; i < m; ++i) {
    int u, v;
    do {
      u = rand() % n;
      v = rand() % n;
    } while (u == v);
    g.addEdge(u, v);
  }
  tick();
  StrongConnectedComponents scc(g);
  cout << scc.n << endl;
  cout << tick() << endl;
}

void AOJ_GRL_3_C() {
  int n, m; cin >> n >> m;
  Graph g(n);
  for (int i = 0; i < m; ++i) {
    int u, v; cin >> u >> v;
    g.addEdge(u, v);
  }
  StrongConnectedComponents scc(g);

  int q; cin >> q;
  for (int i = 0; i < q; ++i) {
    int u, v; cin >> u >> v;
    cout << (scc.index[u] == scc.index[v]) << endl;
  }
}

int main() {
  AOJ_GRL_3_C();
  //test();
}



Measured memory_bytes: 3836