// Original C++ solution (slower):
/**

 * http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_C&lang=jp

 */



// clang-format off

#include <bits/stdc++.h>



#define FOR(i, a, b) for(int i = (a); i < (b); i++)

#define RFOR(i, a, b) for(int i = (b)-1; i >= (a); i--)

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

#define rep1(i,n) for(int i = 1; i <= (n); i++)

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



#define pb push_back

#define mp make_pair

#define fst first

#define snd second

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

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

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

#define pii pair<int, int>

#define vi vector<int>



using namespace std;

template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T>& p){return o<<"("<<p.first<<","<<p.second<<")";}

template<class T> ostream& operator<<(ostream& o,const vector<T>& vc){o<<"sz = "<<vc.size()<<endl<<"[";for(const T& v:vc) o<<v<<",";o<<"]";return o;}

using ll = long long;

constexpr ll MOD = 1000000007;



// ??°???????????????

using Weight = bool;



template <std::size_t SIZE>

struct GraphArray {

    GraphArray(const std::size_t V) : V(V)

    {

        for (std::size_t i = 0; i < V; i++) {

            for (std::size_t j = 0; j < V; j++) {

                weight[i][j] = 0;

            }

        }

    }

    const std::size_t V;

    Weight weight[SIZE][SIZE];

};



struct Edge {

    std::size_t from;

    std::size_t to;

    Weight cost;

};



template <std::size_t SIZE>

struct GraphList {

    GraphList(const std::size_t V) : V(V) {}

    void insert(const std::size_t from, const std::size_t to, const Weight cost = 1)

    {

        edge[from].push_back(Edge{from, to, cost});

    }



    GraphList reversed() const

    {

        GraphList g(V);

        for (std::size_t from = 0; from < V; from++) {

            for (const auto& e : edge[from]) {

                g.insert(e.to, from, e.cost);

            }

        }

        return g;

    }



    const std::size_t V;

    std::vector<Edge> edge[SIZE];

};



// ?????£?????????????§£

template <std::size_t SIZE>

void dfs1(const GraphList<SIZE>& g, const std::size_t s, std::size_t cmp[SIZE], std::stack<std::size_t>& st)

{

    cmp[s] = 0;

    for (const auto& e : g.edge[s]) {

        if (cmp[e.to]) {

            dfs1(g, e.to, cmp, st);

        }

    }

    st.push(s);

};



template <std::size_t SIZE>

void dfs2(const GraphList<SIZE>& rg, const std::size_t s, const std::size_t index, std::size_t cmp[SIZE])

{

    cmp[s] = index;

    for (const auto& e : rg.edge[s]) {

        if (cmp[e.to] == std::numeric_limits<std::size_t>::max()) {

            dfs2(rg, e.to, index, cmp);

        }

    }

};



template <std::size_t SIZE>

void SCC(const GraphList<SIZE>& g, std::size_t cmp[SIZE])

{

    std::stack<std::size_t> st;

    for (std::size_t i = 0; i < g.V; i++) {

        cmp[i] = 1;

    }



    for (std::size_t i = 0; i < g.V; i++) {

        if (cmp[i]) {

            dfs1(g, i, cmp, st);

        }

    }



    const GraphList<SIZE> rg = g.reversed();

    for (std::size_t i = 0; i < g.V; i++) {

        cmp[i] = std::numeric_limits<std::size_t>::max();

    }



    std::size_t comp = 0;

    while (not st.empty()) {

        const std::size_t s = st.top();

        st.pop();

        if (cmp[s] == std::numeric_limits<std::size_t>::max()) {

            dfs2(rg, s, comp, cmp);

            comp++;

        }

    }

}



constexpr std::size_t MAX = 10000;

std::size_t cmp[MAX];



int main()

{

    std::size_t V, E, Q;

    cin >> V >> E;

    GraphList<MAX> g(V);

    rep(i, E){

        std::size_t s, t;

        cin >> s >> t;

        g.insert(s, t);

    }

    SCC(g, cmp);

    cin >> Q;

    rep(i, Q){

        std::size_t u, v;

        cin >> u >> v;

        if(cmp[u] == cmp[v]){

            cout << "1" << endl;

        } else {

            cout << "0" << endl;

        }

    }

    return 0;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



// Just stands for connections

class LinkList

{

public:

    LinkList(const std::size_t v) : m_v{v}

    {

        m_table.resize(v);

        m_reversed_table.resize(v);

    }

    void addEdge(const std::size_t from, const std::size_t to)

    {

        m_e++;

        m_table[from].push_back(to);

        m_reversed_table[to].push_back(from);

    }



    void TopologocalSort(std::vector<std::size_t>& srt) const

    {

        assert(srt.size() == m_v);

        std::vector<bool> yet(m_v, true);

        std::size_t pos = m_v - 1;

        for (std::size_t i = 0; i < m_v; i++) {

            dfs_topo(i, yet, srt, pos);

        }

    }



    std::size_t SCC(std::vector<std::size_t>& cmp) const

    {

        assert(cmp.size() == m_v);

        for (std::size_t i = 0; i < m_v; i++) {

            cmp[i] = 0;

        }



        std::vector<std::size_t> st;

        std::vector<bool> used(m_v, false);

        for (std::size_t i = 0; i < m_v; i++) {

            if (not used[i]) {

                dfs1_scc(i, st, used);

            }

        }



        for (std::size_t i = 0; i < m_v; i++) {

            used[i] = false;

        }

        std::size_t comp = 0;

        for (std::size_t i = 0; i < st.size(); i++) {

            const std::size_t s = st[st.size() - i - 1];

            if (not used[s]) {

                dfs2_scc(s, comp++, cmp, used);

            }

        }

        return comp;

    }



    std::size_t getV() const

    {

        return m_v;

    }



    std::size_t getE() const

    {

        return m_e;

    }



    const std::vector<std::vector<std::size_t>>& getEdge() const

    {

        return m_table;

    }



    std::vector<std::vector<std::size_t>>& getEdge()

    {

        return m_table;

    }



    const std::vector<std::vector<std::size_t>>& getReversedEdge() const

    {

        return m_reversed_table;

    }



    std::vector<std::vector<std::size_t>>& getReversedEdge()

    {

        return m_reversed_table;

    }



    void printDot() const

    {

        std::cout << "digraph \"Graph\" {\n";



        std::cout << "  graph [\n"

                  << "    charset = \"UTF-8\";\n"

                  << "    label = \"Graph\",\n"

                  << "    labelloc = \"t\",\n"

                  << "    labeljust = \"c\",\n"

                  << "    bgcolor = \"#343434\",\n"

                  << "    fontcolor = white,\n"

                  << "    fontsize = 18,\n"

                  << "    style = \"filled\",\n"

                  << "    rankdir = TB,\n"

                  << "    margin = 0.2,\n"

                  << "    splines = spline,\n"

                  << "    ranksep = 1.0,\n"

                  << "    nodesep = 0.9,\n"

                  << "    layout = dot\n"

                  << "  ];\n\n";



        std::cout << "  node [\n"

                  << "    colorscheme = \"rdylgn11\"\n"

                  << "    style = \"solid,filled\",\n"

                  << "    fontsize = 16,\n"

                  << "    fontcolor = 6,\n"

                  << "    fontname = \"Migu 1M\",\n"

                  << "    color = 7,\n"

                  << "    fillcolor = 11,\n"

                  << "    fixedsize = true,\n"

                  << "    height = 0.6,\n"

                  << "    width = 1.2\n"

                  << "  ];\n\n";



        std::cout << "  edge [\n"

                  << "    style = solid,\n"

                  << "    fontsize = 14,\n"

                  << "    fontcolor = white,\n"

                  << "    fontname = \"Migu 1M\",\n"

                  << "    color = white,\n"

                  << "    labelfloat = true,\n"

                  << "    labeldistance = 2.5,\n"

                  << "    labelangle = 70\n"

                  << "  ];\n\n";



        std::cout << "  // Node definition\n";

        for (std::size_t i = 0; i < m_v; i++) {

            std::cout << "  " << i << ";\n";

        }

        std::cout << "\n";

        std::cout << "  // Edge definition\n";

        for (std::size_t i = 0; i < m_v; i++) {

            for (const std::size_t to : m_table[i]) {

                std::cout << "  " << i << " -> " << to << ";\n";

            }

        }

        std::cout << "}" << std::endl;

    }





private:

    void dfs_topo(const std::size_t s, std::vector<bool>& yet, std::vector<std::size_t>& st, std::size_t& pos) const

    {

        assert(s < m_v);

        assert(yet.size() == m_v);

        assert(st.size() == m_v);

        assert(pos < m_v);

        yet[s] = false;

        for (const std::size_t to : m_table[s]) {

            if (yet[to]) {

                dfs_topo(to, yet, st, pos);

            }

        }

        st[pos] = s;

        pos--;

    }



    void dfs1_scc(const std::size_t s, std::vector<std::size_t>& st, std::vector<bool>& used) const

    {

        assert(s < m_v);

        assert(used.size() == m_v);

        used[s] = true;

        for (const std::size_t to : m_table[s]) {

            if (not used[to]) {

                dfs1_scc(to, st, used);

            }

        }

        st.push_back(s);

    }



    void dfs2_scc(const std::size_t s, const std::size_t index, std::vector<std::size_t>& cmp, std::vector<bool>& used) const

    {

        assert(s < m_v);

        assert(index < m_v);

        assert(cmp.size() == m_v);

        cmp[s] = index;

        used[s] = true;

        for (const std::size_t to : m_reversed_table[s]) {

            if (not used[to]) {

                dfs2_scc(to, index, cmp, used);

            }

        }

    };



    const std::size_t m_v;

    std::size_t m_e;

    std::vector<std::vector<std::size_t>> m_table;

    std::vector<std::vector<std::size_t>> m_reversed_table;

};



int main()

{

    std::size_t V, E;

    std::cin >> V >> E;

    LinkList g{V};

    for (std::size_t i = 0; i < E; i++) {

        std::size_t s, t;

        std::cin >> s >> t;

        g.addEdge(s, t);

    }

    std::vector<std::size_t> cmp(V);

    g.SCC(cmp);



    std::size_t Q;

    std::cin >> Q;

    for (std::size_t i = 0; i < Q; i++) {

        std::size_t u, v;

        std::cin >> u >> v;

        if (cmp[u] == cmp[v]) {

            std::cout << 1 << std::endl;

        } else {

            std::cout << 0 << std::endl;

        }

    }



    return 0;

}

// Fastest known solution for this problem: