// Slower C++ solution:
#include<iostream>

#include<vector>

#include<algorithm>

#include<cstdio>

#include<cstring>



using namespace std;



const int MAX_N = 10000;

const int V = 10000;



vector<int> G[MAX_N];

vector<int> rG[MAX_N];

vector<int> vs; //??°?????????????????????

bool used[MAX_N]; //?????§????????????????????????

int cmp[MAX_N];	//?±????????????£????????????????????????????????????



void add_edge(int from,int to)

{

	G[from].push_back(to);

	rG[to].push_back(from);

}



void dfs(int v)

{

	used[v] = true;

	for(int i=0;i<G[v].size();i++){

		if(!used[G[v][i]]){

			dfs(G[v][i]);

		}

	}

	vs.push_back(v);

}



void rdfs(int v,int k)

{

	used[v] = true;

	cmp[v] = k;

	for(int i=0;i<rG[v].size();i++){

		if(!used[rG[v][i]]){

			rdfs(rG[v][i],k);

		}

	}

}



int scc()	//?????£??????????????°?????????

{

	memset(used,0,sizeof(used));

	vs.clear();

	for(int v=0;v<V;v++){

		if(!used[v]){

			dfs(v);

		}

	}

	memset(used,0,sizeof(used));

	int k=0;

	for(int i=vs.size()-1;i>=0;i--){

		if(!used[vs[i]]){

			rdfs(vs[i],k++);

		}

	}

	return k;

}



int main()

{

	int n,m,from,to,k,l,u,v;

	cin >> n >> m;

	for(int i=0;i<m;i++){

		cin >> from >> to;

		add_edge(from,to);

	}

	k = scc();	

	cin >> l;

	for(int i=0;i<l;i++){

		cin >> u >> v;

		printf("%d\n",(cmp[u] == cmp[v]));

	}

}

// Faster C++ solution for the same problem (measured speedup: 1.7059599026597903x):
#include <bits/stdc++.h>

#define ll long long

#define INF 1000000005

#define MOD 1000000007

#define EPS 1e-10

#define rep(i,n) for(int i=0;i<(int)(n);++i)

#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)

#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)

#define each(a,b) for(auto& (a): (b))

#define all(v) (v).begin(),(v).end()

#define len(v) (int)(v).size()

#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())

#define cmx(x,y) x=max(x,y)

#define cmn(x,y) x=min(x,y)

#define fi first

#define se second

#define pb push_back

#define show(x) cout<<#x<<" = "<<(x)<<endl

#define sar(a,n) {cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl;}



using namespace std;



template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}

template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}

template<typename S,typename T,typename U>

auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}

template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>&m){for(auto&e:m)o<<e<<" ";return o;}

template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}

void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}

template<typename S,typename T,typename U>

struct TRI{S fi;T se;U th;TRI(){}TRI(S f,T s,U t):fi(f),se(s),th(t){}

bool operator<(const TRI&_)const{return(fi==_.fi)?((se==_.se)?(th<_.th):(se<_.se)):(fi<_.fi);}};

template<typename S,typename T,typename U>

auto&operator<<(ostream&o,TRI<S,T,U>&t){return o<<"{"<<t.fi<<","<<t.se<<","<<t.th<<"}";}



typedef pair<int, int> P;

typedef pair<ll, ll> pll;

typedef TRI<int, int, int> tri;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef vector<vi> vvi;

typedef vector<vl> vvl;

typedef vector<P> vp;

typedef vector<double> vd;

typedef vector<string> vs;



const int MAX_N = 100005;



class SCC {

private:

    const int V;

    vector<vector<int> > G;

    vector<int> ord, low;

    stack<int> st;

    void dfs(const int u, int& tm, int& cnt){

        ord[u] = low[u] = tm++, st.push(u);

        for(int v : G[u]){

            if(ord[v] < 0){

                dfs(v, tm, cnt);

                low[u] = min(low[u], low[v]);

            }else if(cmp[v] < 0){

                low[u] = min(low[u], ord[v]);

            }

        }

        if(ord[u] == low[u]){

            while(true){

                const int v = st.top();

                st.pop();

                cmp[v] = cnt;

                if(v == u) break;

            }

            ++cnt;

        }

    }

public:

    vector<vector<int> > dag_graph;

    vector<int> cmp;

    int cnt;

    SCC(const int node_size)

        : V(node_size), G(V), ord(V, -1), low(V), cmp(V, -1), cnt(0){}

    void add_edge(const int from, const int to){

        G[from].push_back(to);

    }

    int solve(){

        int tm = 0;

        for(int i = 0; i < V; ++i){

            if(ord[i] < 0) dfs(i, tm, cnt);

        }

        for(int i = 0; i < V; ++i) cmp[i] = cnt - 1 - cmp[i];

        return cnt;

    }

    void make_graph(){

        dag_graph.resize(cnt);

        for(int i = 0; i < V; ++i){

            for(int j : G[i]){

                if(cmp[i] != cmp[j]){

                    dag_graph[cmp[i]].push_back(cmp[j]);

                }

            }

        }

    }

};



int main()

{

    cin.tie(0);

    ios::sync_with_stdio(false);

    int n, m;

    cin >> n >> m;

    SCC scc(n);

    rep(i,m){

        int a, b;

        cin >> a >> b;

        scc.add_edge(a, b);

    }

    scc.solve();

    int q;

    cin >> q;

    rep(i,q){

        int u,v;

        cin >> u >> v;

        cout << (scc.cmp[u] == scc.cmp[v]) << "\n";

    }

    return 0;

}