Problem:
Strongly Connected Components

A direced graph is strongly connected if every two nodes are reachable from each other. In a strongly connected component of a directed graph, every two nodes of the component are mutually reachable.

Input

A directed graph G(V, E) and a sequence of queries where each query contains a pair of nodes u and v.

|V| |E|
s0 t0
s1 t1
:
s|E|-1 t|E|-1
Q
u0 v0
u1 v1
:
uQ-1 vQ-1

|V| is the number of nodes and |E| is the number of edges in the graph. The graph nodes are named with the numbers 0, 1,..., |V|-1 respectively.

si and ti represent source and target nodes of i-th edge (directed).

ui and vi represent a pair of nodes given as the i-th query.

Output

For each query, pinrt "1" if the given nodes belong to the same strongly connected component, "0" otherwise.

Constraints

1 ≤ |V| ≤ 10,000

0 ≤ |E| ≤ 30,000

1 ≤ Q ≤ 100,000

Sample Input 1

5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

Sample Output 1

1
0
1
1

Solution in Rust (judge verdict: Accepted)

macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; ( iter = $ iter : ident , $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut $ iter = s . split_whitespace ( ) ; input_inner ! { $ iter , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut iter = s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; }
macro_rules ! input_inner { ( $ iter : expr ) => { } ; ( $ iter : expr , ) => { } ; ( $ iter : expr , mut $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let mut $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , mut $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , mut $ var : usize $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , $ var : usize $ ( $ r ) * } } ; }
macro_rules ! read_value { ( $ iter : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ iter , $ t ) ) ,* ) } ; ( $ iter : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ iter , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ iter : expr , { chars : $ base : expr } ) => { read_value ! ( $ iter , String ) . chars ( ) . map ( | c | ( c as u8 - $ base as u8 ) as usize ) . collect ::< Vec < usize >> ( ) } ; ( $ iter : expr , { char : $ base : expr } ) => { read_value ! ( $ iter , { chars : $ base } ) [ 0 ] } ; ( $ iter : expr , chars ) => { read_value ! ( $ iter , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ iter : expr , char ) => { read_value ! ( $ iter , chars ) [ 0 ] } ; ( $ iter : expr , usize1 ) => { read_value ! ( $ iter , usize ) - 1 } ; ( $ iter : expr , $ t : ty ) => { $ iter . next ( ) . unwrap ( ) . parse ::<$ t > ( ) . unwrap ( ) } ; }
pub struct StronglyConnectedComponent {
    vsize: usize,
    graph: Vec<Vec<usize>>,
    rgraph: Vec<Vec<usize>>,
    ord: Vec<usize>,
    used: Vec<bool>,
    comp: Vec<usize>,
    csize: usize,
}
impl StronglyConnectedComponent {
    pub fn new(vsize: usize) -> Self {
        StronglyConnectedComponent {
            vsize: vsize,
            graph: vec![vec![]; vsize],
            rgraph: vec![vec![]; vsize],
            ord: vec![],
            used: vec![],
            comp: vec![0; vsize],
            csize: 0,
        }
    }
    pub fn add_edge(&mut self, from: usize, to: usize) {
        self.graph[from].push(to);
        self.rgraph[to].push(from);
    }
    pub fn dfs(&mut self, u: usize) {
        self.used[u] = true;
        for i in 0..self.graph[u].len() {
            let v = self.graph[u][i];
            if !self.used[v] {
                self.dfs(v);
            }
        }
        self.ord.push(u);
    }
    pub fn rdfs(&mut self, u: usize, k: usize) {
        self.used[u] = true;
        self.comp[u] = k;
        for i in 0..self.rgraph[u].len() {
            let v = self.rgraph[u][i];
            if !self.used[v] {
                self.rdfs(v, k);
            }
        }
    }
    pub fn build(&mut self) {
        self.used = vec![false; self.vsize];
        self.ord.clear();
        for u in 0..self.vsize {
            if !self.used[u] {
                self.dfs(u);
            }
        }
        self.used = vec![false; self.vsize];
        self.csize = 0;
        for i in (0..self.vsize).rev() {
            if !self.used[self.ord[i]] {
                let (v, k) = (self.ord[i], self.csize);
                self.rdfs(v, k);
                self.csize += 1;
            }
        }
    }
    pub fn gen_cgraph(&self) -> Vec<Vec<usize>> {
        let mut g = vec![vec![]; self.csize];
        for u in 0..self.vsize {
            for &v in self.graph[u].iter() {
                if self.comp[u] != self.comp[v] {
                    g[self.comp[u]].push(self.comp[v]);
                }
            }
        }
        g.into_iter()
            .map(|v| {
                v.into_iter()
                    .collect::<std::collections::BTreeSet<_>>()
                    .into_iter()
                    .collect::<Vec<_>>()
            })
            .collect::<Vec<_>>()
    }
    pub fn component(&self) -> Vec<std::collections::HashSet<usize>> {
        let mut c = (0..self.csize)
            .map(|_| std::collections::HashSet::new())
            .collect::<Vec<_>>();
        for u in 0..self.vsize {
            c[self.comp[u]].insert(u);
        }
        c
    }
}
fn main() {
    input! { n, m, st: [(usize, usize); m], q, uv: [(usize, usize); q] };
    let mut scc = StronglyConnectedComponent::new(n);
    for (s, t) in st.into_iter() {
        scc.add_edge(s, t);
    }
    scc.build();
    for (u, v) in uv.into_iter() {
        println!("{}", (scc.comp[u] == scc.comp[v]) as usize);
    }
}