// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_C&lang=jp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, j) for(int i = 0; i < (int)(j); i++)
constexpr int INF = 1 << 28;
using EdgeList = vector<vector<int>>;
// ?????£?????????????????°?????? E ????????£????????????????§£(Tarjan's algorithm)
// O(N + M) N: ????????°, M: ?????°
vector<vector<int>> strongly_connected_components_tarjan(const EdgeList &E) {
    int N = E.size();
    vector<int> ord(N, -1), low(N);
    int cnt = 0;
    stack<int> stk;
    vector<bool> on_stack(N);
    vector<vector<int>> scc;    
    function<void(int, int)> dfs = [&] (int now, int pre) {
        stk.push(now);
        on_stack[now] = true;
        ord[now] = cnt++;
        low[now] = ord[now];
        for(int nxt : E[now]) {
            if(ord[nxt] < 0) {
                // not visited
                dfs(nxt, now);
                low[now] = min(low[now], low[nxt]);
            } else if(on_stack[nxt]) {
                // visited
                low[now] = min(low[now], ord[nxt]);
            } 
        }
        if(ord[now] == low[now]) {
            scc.push_back({});
            while(true) {
                int v = stk.top(); stk.pop();
                scc.back().push_back(v);
                on_stack[v] = false;
                if(v == now) break;
            }
        }
    };
    // ??£?????°????????????dfs(0)????????§OK
    rep(i, N) if(ord[i] < 0) dfs(i, -1);
    return scc;
}
// ????????°?????????????????????????????????????????????
bool detect_cycle_tarjan(const EdgeList &E) {
    auto scc = strongly_connected_components_tarjan(E);
    bool res = false;
    for(auto &g : scc) res |= g.size() > 1;
    return res;
}
// ????????°?????? E ????????£????????????????§£(?????¬)
// O(N + M) N: ????????°, M: ?????°
// -> ??????????????????????????????????????????????????????????????£????????????0 ??? root
vector<int> strongly_connected_components_ant(const EdgeList &E) {
    int N = E.size();
    EdgeList rE(N); rep(i, N) for(int nxt : E[i]) rE[nxt].push_back(i); // ??????    
    vector<char> used(N);
    vector<int> vs; // DFS??°????????????
    vector<int> topological_no(N);
    function<void(int)> dfs = [&] (int v) {
        used[v] = true;
        for(int nxt : E[v]) if(not used[nxt]) dfs(nxt);
        vs.push_back(v);
    };
    function<void(int, int)> rdfs = [&] (int v, int k) {
        topological_no[v] = k;
        used[v] = true;
        for(int nxt : rE[v]) if(not used[nxt]) rdfs(nxt, k);
    };
    rep(v, N) if(not used[v]) dfs(v);
    fill(begin(used), end(used), false);
    int k = 0;
    for(int i = vs.size() - 1; i >= 0; i--) if(not used[vs[i]]) rdfs(vs[i], k++);
    return topological_no;
}
// ????????°?????????????????????????????????????????????
bool detect_cycle_ant(const EdgeList &E) {
    auto scc = strongly_connected_components_ant(E);
    set<int> found;
    for(int v : scc) {
        if(found.count(v)) return true;
        found.insert(v);
    }
    return false;
}
#define all(v) v.begin(),v.end()
struct UnionFind{
    int n;
    vector<int> p;
    UnionFind(int nn):n(nn) {
        p.resize(n);
        rep(i, n) p[i] = i;
    }
    int root(int x) {
        return p[x] == x ? x : (p[x] = root(p[x]));
    }
    void unite(int x,int y) {
        x = root(x); y = root(y);
        if(x != y) p[y] = x;
    }
    bool query(int x,int y){
        return root(x) == root(y);
    }
};
int main() {
    int N, M; cin >> N >> M;
    EdgeList E(N);
    rep(i, M) {
        int a, b; cin >> a >> b;
        E[a].push_back(b);
    }
    auto scc = strongly_connected_components_tarjan(E);
    auto scc2 = strongly_connected_components_ant(E);
    
    UnionFind uf(N);
    for(auto &group : scc) for(int v : group) uf.unite(group.front(), v);
    
    int Q; cin >> Q;    
    rep(i, Q) {
        int u, v; cin >> u >> v;
        bool ans = uf.query(u, v);
        bool ans2 = scc2[u] == scc2[v];
        assert(ans == ans2);
        cout << ans << endl;
    }
    return 0;
}

Measured memory_bytes: 5588