#include <iostream>
#include <iomanip>
#include <climits>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <list>
#include <stack>
#include <string>
#include <functional>
#include <numeric>
#include <unordered_map>
#include <map>
#include <set>
#include <cstdlib>
#include <bitset>
#include <random>
#define _USE_MATH_DEFINES
#include <math.h>

using namespace std;

#define INF (int)1e8
#define _INF (int)-1e8
#define INFLL (long long)1e15
#define _INFLL (long long)-1e15
#define Loop(i, n) for(int i = 0; i < (int)n; i++)
#define Loop1(i, n) for(int i = 1; i <= (int)n; i++)
#define Loopr(i, n) for(int i = (int)n - 1; i >= 0; i--)
#define Loopr1(i, n) for(int i = (int)n; i >= 1; i--)
#define bitmanip(m,val) static_cast<bitset<(int)m>>(val)
typedef long long int ll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef pair<int, int> P;

/*******************************************************/

class Union_Find {
private:
	vi parent, rank;
	int find(int x) {
		if (parent[x] == x) return x;
		else return parent[x] = find(parent[x]);
	}
public:
	Union_Find(int N) {
		parent.resize(N);
		rank.resize(N);
		Loop(i, N) {
			parent[i] = i;
			rank[i] = 0;
		}
	}
	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		if (rank[x] < rank[y]) parent[x] = y;
		else {
			parent[y] = x;
			if (rank[x] == rank[y]) rank[x]++;
		}
	}
	bool is_same(int x, int y) {
		return find(x) == find(y);
	}
};

struct graph_t {
	int n;           // |V|, index begins with 0
	int m;           // |E|
	vector<P> edges; // E
	vector<ll> cost; // cost or distance
	vector<ll> cap;  // capacity
};

class Strongly_Connected_Components {
private:
	struct node {
		int id; bool done; vi to_eid; vi to; int from_eid; int from;
	};
	vector<node> nodes[2];
	int n;
	stack<int> stk;
	vvi sccs;
	void scc_dfs(int a, int is_r) {
		nodes[is_r][a].done = true;
		Loop(i, nodes[is_r][a].to.size()) {
			int b = nodes[is_r][a].to[i];
			if (b == nodes[is_r][a].from) continue;
			if (!nodes[is_r][b].done) {
				nodes[is_r][b].from = a;
				scc_dfs(b, is_r);
			}
		}
		if (is_r == 0) stk.push(a);
		else {
			sccs.back().push_back(a);
		}
		return;
	}
public:
	Strongly_Connected_Components(graph_t G) {
		n = G.n;
		Loop(i, 2) nodes[i].resize(n);
		Loop(i, 2) {
			Loop(j, n) nodes[i][j] = { i, false,{},{}, -1, -1 };
		}
		Loop(i, G.edges.size()) {
			nodes[0][G.edges[i].first].to_eid.push_back(i);
			nodes[0][G.edges[i].first].to.push_back(G.edges[i].second);
			nodes[1][G.edges[i].second].to_eid.push_back(i);
			nodes[1][G.edges[i].second].to.push_back(G.edges[i].first);
		}
		Loop(j, n) {
			if (!nodes[0][j].done) scc_dfs(j, 0);
		}
		while (stk.size()) {
			int a = stk.top(); stk.pop();
			if (!nodes[1][a].done) {
				sccs.push_back({});
				scc_dfs(a, 1);
				sort(sccs.back().begin(), sccs.back().end());
			}
		}
		sort(sccs.begin(), sccs.end());
		return;
	}
	vvi get_sccs() {
		return sccs;
	}
};

// strongly_connected_components sample
int main() {
	graph_t G;
	cin >> G.n >> G.m;
	Loop(i, G.m) {
		int s, t; cin >> s >> t;
		G.edges.push_back({ s, t });
	}
	Strongly_Connected_Components scc(G);
	vvi sccs = scc.get_sccs();
	Union_Find uf(G.n);
	Loop(i, sccs.size()) {
		Loop(j, sccs[i].size()) {
			uf.unite(sccs[i][0], sccs[i][j]);
		}
	}
	int q; cin >> q;
	Loop(i, q) {
		int a, b; cin >> a >> b;
		if (uf.is_same(a, b)) cout << 1 << endl;
		else cout << 0 << endl;
	}
	return 0;
}

Measured memory_bytes: 6104