import java.util.*

class UnionFindTree{
    private var mParent:UnionFindTree? = null
    private fun Parent():UnionFindTree {
        return when(mParent) {
            null -> this
            else -> {
                mParent = mParent!!.Parent()
                mParent !!
            }
        }
    }
    fun Join(other:UnionFindTree):Unit {
        if (!IsSameUnion(other)){
            Parent().mParent = other.Parent()
        }
    }
    fun IsSameUnion(other:UnionFindTree):Boolean = Parent() == other.Parent()
}
data class Edge(val from:Node, val to:Node)
class Node(val Id:Int){
    private var mForwardEdges: LinkedList<Node> = LinkedList()
    private var mReverseEdges: LinkedList<Node> = LinkedList()
    fun ForwardEdges():LinkedList<Node> = mForwardEdges
    fun ReverseEdges():LinkedList<Node> = mReverseEdges
    fun AddEdge(edge:Edge):Unit {
        val (from, to) = edge
        when{
            from == this -> mForwardEdges.push(to)
            to == this -> mReverseEdges.push(from)
        }
    }
}
fun StackedDFS(current:Node, numArray: Array<Int>, init:Int):Int {
    val stack = Stack<Node>().apply{push(current)}
    var i = init
    while (!stack.empty()){
        when(numArray[stack.peek().Id]) {
            -1 -> {
                numArray[stack.peek().Id] = 0//DFSで訪問済み
                stack.peek().ForwardEdges().forEach { if (numArray[it.Id] == -1) stack.push(it) }//新たな訪問先を設定
            }
            0 -> {//ロールバックで再度訪問
                i += 1
                numArray[stack.peek().Id] = i
                stack.pop()
            }
            else -> stack.pop()
        }
    }
    return i
}
fun StackedInvDFS(current:Node, uft:Array<UnionFindTree>, isSearched: Array<Boolean>, numArray: Array<Int>, start:Int):Unit{
    val stack = Stack<Node>().apply{push(current)}
    while (!stack.empty()){
        when(isSearched[stack.peek().Id]){
            true -> stack.pop()
            false -> {
                isSearched[stack.peek().Id] = true
                stack.pop().ReverseEdges().forEach {
                    when(!isSearched[it.Id] && start > numArray[it.Id]){
                        true -> {
                            uft[current.Id].Join(uft[it.Id])
                            stack.push(it)
                        }
                    }
                }
            }
        }
    }
}

fun main(args:Array<String>):Unit{
    val (v, e) = readLine()!!.split(' ').map(String::toInt)
    val nodes = Array(v){Node(it)}
    for (i in 0 until e){
        val (from, to) = readLine()!!.split(' ').map(String::toInt)
        val edge = Edge(nodes[from], nodes[to])
        edge.from.AddEdge(edge)
        edge.to.AddEdge(edge)
    }
    val nums = Array(v){-1}
    nodes.fold(0){ init, node ->
        if (nums[node.Id] == -1)
            StackedDFS(node, nums, init)
        else
            init
    }
    val isSearched = Array(v){false}
    val uft = Array(v){UnionFindTree()}
    nums.withIndex().sortedByDescending { it.value }.map {
        nodes[it.index]
    }.forEach { node ->
        if (!isSearched[node.Id]){
            StackedInvDFS(node, uft, isSearched, nums, nums[node.Id])
        }
    }
    for (i in 0 until readLine()!!.toInt()){
        val (a, b) = readLine()!!.split(' ').map(String::toInt)
        println(if (uft[a].IsSameUnion(uft[b])) 1 else 0)
    }
}


Measured memory_bytes: 79576