#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using namespace std;

using edge=struct{int to;};
using G=vector<vector<edge>>;
inline bool operator<(const edge &a,const edge &b){return a.to < b.to;};


//WF scc n<=100
// void wf_scc(){
// 	rep(k,n)rep(i,n)rep(j,n) graph[i][j]|=(graph[i][k] && graph[k][j]);
// 	init(par,n);
// 	rep(i,n) rep(j,n) if(graph[i][j]&&graph[j][i]) unite(par,i,j);
// }

//tuple<vector<int>,G> 

/*
auto scc(const G &graph){
	int n=graph.size(),k=0,m=0;
	vector<int> ord(n,-1),low(n),comp(n,-1),par(n);
	stack<int>s;

	function<void(int,int)> dfs=[&](int v,int p){
		ord[v]=k++,low[v]=ord[v],par[v]=p;
		s.push(v);

		for(auto &e:graph[v]){
			if(ord[e.to]==-1){
				dfs(e.to,v);
				chmin(low[v],low[e.to]);
			}else if(comp[e.to]==-1){
				chmin(low[v],ord[e.to]);
			}
		}

		if(ord[v]==low[v]){
			while(1){
				int u=s.top();s.pop();
				comp[u]=m;
				if(u==v) break;
			}
			m++;
		}
	};

	rep(v,n) if(ord[v]==-1) dfs(v,-1);
	G dag(m);

	rep(v,n){
		set<edge> cur;
		for(auto &e:graph[v]){
			if(comp[v]==comp[e.to]) continue;
			cur.insert({comp[e.to]});
		}
		dag[v]=vector<edge>(_all(cur));
	}
	return make_tuple(comp,dag);
}
*/

tuple<vector<int>,G> scc(const G &graph,const G &rev){
	int n=graph.size(),m=0;
	vector<int> ord,comp(n,0);
	
	function<void(int)> dfs=[&](int v){
		comp[v]=-1;
		for(auto &e:graph[v]) if(comp[e.to]==0) dfs(e.to);
		ord.push_back(v);
	};

	function<void(int)> rdfs=[&](int v){
		comp[v]=m;
		for(auto &e:rev[v]) if(comp[e.to]==-1) rdfs(e.to);
	};

	rep(v,n) if(comp[v]==0) dfs(v);
	rrep(v,n) if(comp[ord[v]]==-1) rdfs(ord[v]),m++;

	G dag(m);
	return make_tuple(comp,dag);

	rep(v,n){
		set<edge> cur;
		for(auto &e:graph[v]){
			if(comp[v]==comp[e.to]) continue;
			cur.insert({comp[e.to]});
		}
		dag[v]=vector<edge>(_all(cur));
	}

	return make_tuple(comp,dag);
}


/*
auto topological_sort(const G &graph) {
	int n=graph.size();
	vector<int> order,used(n,false);
	
	function<void(int)> dfs=[&](int v){
		used[v]=true;
		for(auto &e:graph[v]){
			if(!used[e.to])
				dfs(e.to);
		}
		order.push_back(v);
	};

	rep(v,n) if(!used[v]) dfs(v);
	reverse(_all(order));
	return order;
}
*/

int main(void){
	int v,e;
	cin >> v >> e;

	G graph(v),rev(v);
	rep(loop,e){
		int a,b;
		cin >> a >> b;
		graph[a].push_back({b});
		rev[b].push_back({a});
	}

	vector<int> comp;
	tie(comp,ignore)=scc(graph,rev);

	int q;
	cin >> q;
	rep(loop,q){
		int a,b;
		cin >> a >> b;
		cout << (comp[a]==comp[b]) << endl;
	}
	return 0;
}

Measured memory_bytes: 4808