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|  s 0  t 0  s 1  t 1 : s |E|-1  t |E|-1  Q  u 0  v 0  u 1  v 1 : u Q-1  v Q-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.  s i and t i represent source and target nodes of i -th edge (directed).  u i and v i 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 (Python):




from collections import namedtuple


DirectedEdge = namedtuple('DirectedEdge', ('src', 'dest'))


def revert(edge):
    return edge._replace(src=edge.dest, dest=edge.src)


class Digraph:
    def __init__(self, v):
        self.v = v
        self._edges = [[] for _ in range(v)]

    def add(self, edge):
        self._edges[edge.src].append(edge)

    def adj(self, v):
        return self._edges[v]

    def edges(self):
        for es in self._edges:
            for e in es:
                yield e

    def reversed(self):
        g = self.__class__(self.v)
        for e in self.edges():
            g.add(revert(e))

        return g


def reverse_post(graph):
    def visit(v):
        if not visited[v]:
            visited[v] = True
            return True
        else:
            return False

    def leave(v):
        if not left[v]:
            left[v] = True
            vs.append(v)
        return False

    visited = [False] * graph.v
    left = [False] * graph.v
    vs = []

    for i in range(graph.v):
        if not visited[i]:
            stack = [(i, leave)]
            stack.extend((e.dest, visit) for e in graph.adj(i))
            while stack:
                v, f = stack.pop()
                if f(v):
                    stack.append((v, leave))
                    for e in graph.adj(v):
                        stack.append((e.dest, visit))
    return reversed(vs)


def scc_kosaraju_sharir(graph):
    class CC:
        def __init__(self, v):
            self._id = [i for i in range(v)]

        def id(self, v, c):
            self._id[v] = c

        def connected(self, u, v):
            return self._id[u] == self._id[v]

    def dfs(v):
        stack = [v]
        while stack:
            w = stack.pop()
            if not visited[w]:
                visited[w] = True
                yield w
                stack.extend([e.dest for e in graph.adj(w)
                              if not visited[e.dest]])

    visited = [False] * graph.v
    i = 0
    cc = CC(graph.v)
    for v in reverse_post(graph.reversed()):
        if not visited[v]:
            for w in dfs(v):
                cc.id(w, i)
            i += 1
    return cc


def run():
    v, e = [int(i) for i in input().split()]
    g = Digraph(v)

    for _ in range(e):
        s, t = [int(i) for i in input().split()]
        g.add(DirectedEdge(s, t))

    cc = scc_kosaraju_sharir(g)
    q = int(input())
    for _ in range(q):
        u, w = [int(i) for i in input().split()]
        if cc.connected(u, w):
            print(1)
        else:
            print(0)


if __name__ == '__main__':
    run()

Solution (Python):


import sys

sys.setrecursionlimit(10 ** 9)
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
INF=float('inf')

N,M=MAP()
nodes1=[[] for i in range(N)]
nodes2=[[] for i in range(N)]
for i in range(M):
    u,v=MAP()
    nodes1[u].append(v)
    nodes2[v].append(u)

T=[]
visited=[False]*N
def rec1(cur):
    visited[cur]=True
    for nxt in nodes1[cur]:
        if not visited[nxt]:
            rec1(nxt)
    
    T.append(cur)


for u in range(N):
    if not visited[u]:
        rec1(u)

visited=[False]*N
group=[0]*N
grpnum=1
def rec2(cur):
    global grpnum
    group[cur]=grpnum
    visited[cur]=True
    for nxt in nodes2[cur]:
        if not visited[nxt]:
            rec2(nxt)


for u in reversed(T):
    if not visited[u]:
        rec2(u)
        grpnum+=1

Q=INT()
for _ in range(Q):
    u,v=MAP()
    if group[u]==group[v]:
        print(1)
    else:
        print(0)

Solution (Python):
from collections import UserList
class Stack(UserList):
    def __init__(self):
        UserList.__init__(self)
        self.contains = set()
    def __contains__(self, x):
        return x in self.contains
    def __and__(self, x):
        return self.contains & x
    def push(self, x):
        if x in self.contains:
            return
        self.data.append(x)
        self.contains |= {x}
    def pop(self):
        x = self.data.pop()
        self.contains -= {x}
        return x

def search(g, g_dash,v):
    
    visited = set()
    postorder = []
    for root in range(v):
        if root in visited:
            continue
        route = Stack()
        route.push(None)
        dfs_stack = [(root, None)]            
        while dfs_stack:
            u, prev = dfs_stack.pop()
            if u in visited:
                continue
            visited |= {u}
            dfs_stack.extend((v, u) for v in g[u] - visited)
            while route[-1] != prev:
                postorder.append(route.pop())
            route.push(u)
        while route[-1] is not None:
            postorder.append(route.pop())

    
    visited.clear()
    lowest = [None] * v
    for root in postorder[::-1]:
        if root in visited:
            continue
        dfs_stack = [root]
        while dfs_stack:
            u = dfs_stack.pop()
            if u in visited:
                continue
            visited |= {u}
            lowest[u] = root
            dfs_stack.extend(g_dash[u] - visited)
    return lowest

from sys import stdin
from collections import defaultdict
readline = stdin.readline

def main():
    v, e = map(int, readline().split())
    g = defaultdict(set)
    g_dash = defaultdict(set)

    for _ in range(e):
        s, t = map(int, readline().split())
        g[s] |= {t}        
        g_dash[t] |= {s}        
    
    lowest = search(g,g_dash, v)
    q = int(readline())
    for u, v in [map(int, readline().split()) for _ in range(q)]:
        print(1 if lowest[u] == lowest[v] else 0)
main()

Solution (Python):
import sys

sys.setrecursionlimit(200000)


def f_dfs(i):
    global f_edges, counter
    visited[i] = True
    for edge in f_edges[i]:
        if visited[edge]:
            continue
        f_dfs(edge)
    finish_order[i] = (counter, i)
    counter += 1


def b_dfs(i, group):
    global b_edges, groups
    visited[i] = True
    groups[i] = group
    for edge in b_edges[i]:
        if visited[edge]:
            continue
        b_dfs(edge, group)


n, m = map(int, input().split())

f_edges = [set() for _ in range(n)]
b_edges = [set() for _ in range(n)]

for _ in range(m):
    s, t = map(int, input().split())
    f_edges[s].add(t)
    b_edges[t].add(s)

visited = [False] * n
finish_order = [None] * n
counter = 0

for i in range(n):
    if not visited[i]:
        f_dfs(i)

visited = [False] * n
groups = [None] * n
group = 0

for d, i in sorted(finish_order, reverse=True):
    if not visited[i]:
        b_dfs(i, group)
        group += 1

q = int(input())

while q:
    q -= 1
    u, v = map(int, input().split())
    print(int(groups[u] == groups[v]))

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""
import sys

sys.setrecursionlimit(int(1e6))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def graph_dfs(u, low, disc, stack_member, st):
    global Time
    
    disc[u] = Time
    low[u] = Time
    Time += 1
    stack_member[u] = True
    st.append(u)
    scc_set = set()

    
    for v in adj_table[u]:

        
        if disc[v] == -1:

            graph_dfs(v, low, disc, stack_member, st)

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

        elif stack_member[v]:

            '''Update low value of 'u' only if 'v' is still in stack
            (i.e. it's a back edge, not cross edge).
            Case 2 (per above discussion on Disc and Low value) '''
            low[u] = min(low[u], disc[v])

    
    w = -1  
    if low[u] == disc[u]:
        while w != u:
            w = st.pop()
            scc_set.add(w)
            stack_member[w] = False
        ans.append(scc_set)

    return None


def scc():
    
    
    
    disc = [-1] * vertices
    low = [-1] * vertices
    stack_member = [False] * vertices
    st = []

    
    
    
    for v in range(vertices):
        if disc[v] == -1:
            graph_dfs(v, low, disc, stack_member, st)

    return ans


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets:
            if (ele1 in each) and (ele2 in each):
                flag = True
        if flag:
            print('1')
        else:
            print('0')
    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    Time = 0
    ans = []
    scc_sets = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""
import sys

sys.setrecursionlimit(int(1e6))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def graph_dfs(u, low, disc, stack_member, st):
    global Time
    
    disc[u] = Time
    low[u] = Time
    Time += 1
    stack_member[u] = True
    st.append(u)
    scc_set = set()

    
    for v in adj_table[u]:

        
        if disc[v] == -1:

            graph_dfs(v, low, disc, stack_member, st)

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

        elif stack_member[v]:

            '''Update low value of 'u' only if 'v' is still in stack
            (i.e. it's a back edge, not cross edge).
            Case 2 (per above discussion on Disc and Low value) '''
            low[u] = min(low[u], disc[v])

    
    w = -1  
    if low[u] == disc[u]:
        while w != u:
            w = st.pop()
            scc_set.add(w)
            stack_member[w] = False
        ans.append(scc_set)

    return None


def scc():
    
    
    
    disc = [-1] * vertices
    low = [-1] * vertices
    stack_member = [False] * vertices
    st = []

    
    
    
    for v in range(vertices):
        if disc[v] == -1:
            graph_dfs(v, low, disc, stack_member, st)

    return ans


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets:
            if (ele1 in each) and (ele2 in each):
                flag = True
        if flag:
            print('1')
        else:
            print('0')
    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    Time = 0
    ans = []
    scc_sets = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""
import sys

sys.setrecursionlimit(int(1e6))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def graph_dfs(u, low, disc, stack_member, st):
    global Time
    
    disc[u] = Time
    low[u] = Time
    Time += 1
    stack_member[u] = True
    st.append(u)
    scc_set = set()

    
    for v in adj_table[u]:

        
        if disc[v] == -1:

            graph_dfs(v, low, disc, stack_member, st)

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

        elif stack_member[v]:

            '''Update low value of 'u' only if 'v' is still in stack
            (i.e. it's a back edge, not cross edge).
            Case 2 (per above discussion on Disc and Low value) '''
            low[u] = min(low[u], disc[v])

    
    w = -1  
    if low[u] == disc[u]:
        while w != u:
            w = st.pop()
            scc_set.add(w)
            stack_member[w] = False
        ans.append(scc_set)

    return None


def scc():
    
    
    
    disc = [-1] * vertices
    low = [-1] * vertices
    stack_member = [False] * vertices
    st = []

    
    
    
    for v in range(vertices):
        if disc[v] == -1:
            graph_dfs(v, low, disc, stack_member, st)

    return ans


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')
    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    Time = 0
    ans = []
    scc_sets = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""
import sys

sys.setrecursionlimit(int(1e6))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def graph_dfs(current, low, disc, stack_member, st):
    global Time
    
    disc[current] = Time
    low[current] = Time
    Time += 1
    stack_member[current] = True
    st.append(current)
    scc_set = set()

    
    for adj in adj_table[current]:

        
        if disc[adj] == -1:

            graph_dfs(adj, low, disc, stack_member, st)

            
            
            
            low[current] = min(low[current], low[adj])

        elif stack_member[adj]:

            '''Update low value of 'current' only if 'adj' is still in stack
            (i.e. it's a back edge, not cross edge).
            Case 2 (per above discussion on Disc and Low value) '''
            low[current] = min(low[current], disc[adj])

    
    scc_candidate = -1  
    if low[current] == disc[current]:
        while scc_candidate != current:
            scc_candidate = st.pop()
            scc_set.add(scc_candidate)
            stack_member[scc_candidate] = False
        ans.append(scc_set)

    return None


def scc():
    
    
    
    disc = [-1] * vertices
    low = [-1] * vertices
    stack_member = [False] * vertices
    st = []

    
    
    
    for v in range(vertices):
        if disc[v] == -1:
            graph_dfs(v, low, disc, stack_member, st)

    return ans


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')
    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    Time = 0
    ans = []
    scc_sets = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""

import sys
from math import isinf

sys.setrecursionlimit(int(1e5))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def Tarjan(current, low, disc, scc_stack, in_scc_stack):
    global timer
    disc[current] = low[current] = timer
    timer += 1

    
    in_scc_stack[current] = True
    scc_stack.append(current)

    current_scc_set = set()
    for adj in adj_table[current]:
        if isinf(disc[adj]):
            Tarjan(adj, low, disc, scc_stack, in_scc_stack)
            low[current] = min(low[current], low[adj])

        elif in_scc_stack[adj]:
            low[current] = min(low[current], disc[adj])

    scc_candidate = -1
    if disc[current] == low[current]:
        while scc_candidate != current:
            scc_candidate = scc_stack.pop()
            current_scc_set.add(scc_candidate)
            
            in_scc_stack[scc_candidate] = False

        init_scc_sets_list.append(current_scc_set)

    return None


def scc():
    disc = [float('inf')] * vertices
    low = [float('inf')] * vertices
    
    scc_stack = list()
    in_scc_stack = [False] * vertices

    for v in range(vertices):
        if isinf(disc[v]):
            Tarjan(v, low, disc, scc_stack, in_scc_stack)

    return init_scc_sets_list


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets_list:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')

    return scc_sets_list


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    timer = 0
    init_scc_sets_list = []
    scc_sets_list = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""

import sys
from math import isinf

sys.setrecursionlimit(int(1e5))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def Tarjan(current, low, disc, scc_stack, in_scc_stack):
    global timer
    disc[current] = low[current] = timer
    timer += 1

    
    in_scc_stack[current] = True
    scc_stack.append(current)

    current_scc_set = set()
    for adj in adj_table[current]:
        if isinf(disc[adj]):
            Tarjan(adj, low, disc, scc_stack, in_scc_stack)
            low[current] = min(low[current], low[adj])

        elif in_scc_stack[adj]:
            low[current] = min(low[current], disc[adj])

    scc_candidate = -1
    if disc[current] == low[current]:
        while scc_candidate != current:
            scc_candidate = scc_stack.pop()
            current_scc_set.add(scc_candidate)
            
            in_scc_stack[scc_candidate] = False

        init_scc_sets_list.append(current_scc_set)

    return None


def scc():
    disc = [float('inf')] * vertices
    low = [float('inf')] * vertices
    
    scc_stack = list()
    in_scc_stack = [False] * vertices

    for v in range(vertices):
        if isinf(disc[v]):
            Tarjan(v, low, disc, scc_stack, in_scc_stack)

    return init_scc_sets_list


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets_list:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    timer = 0
    init_scc_sets_list = []
    scc_sets_list = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""

import sys
from math import isinf

sys.setrecursionlimit(int(1e5))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def Tarjan(current, low, disc, scc_stack, in_scc_stack):
    global timer
    disc[current] = low[current] = timer
    timer += 1

    
    in_scc_stack[current] = True
    scc_stack.append(current)

    current_scc_set = set()
    for adj in adj_table[current]:
        if isinf(disc[adj]):
            Tarjan(adj, low, disc, scc_stack, in_scc_stack)
            low[current] = min(low[current], low[adj])

        elif in_scc_stack[adj]:
            low[current] = min(low[current], disc[adj])

    scc_candidate = -1
    if disc[current] == low[current]:
        while scc_candidate != current:
            scc_candidate = scc_stack.pop()
            current_scc_set.add(scc_candidate)
            
            in_scc_stack[scc_candidate] = False

        init_scc_sets_list.append(current_scc_set)

    return None


def scc():
    disc = [float('inf')] * vertices
    low = [float('inf')] * vertices
    
    scc_stack = list()
    in_scc_stack = [False] * vertices

    for v in range(vertices):
        if isinf(disc[v]):
            Tarjan(v, low, disc, scc_stack, in_scc_stack)

    return init_scc_sets_list


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets_list:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    timer = 0
    init_scc_sets_list = []
    scc_sets_list = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""

import sys
from math import isinf

sys.setrecursionlimit(int(1e5))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def Tarjan(current, low, disc, scc_stack, in_scc_stack):
    global timer
    disc[current] = low[current] = timer
    timer += 1

    in_scc_stack[current] = True
    scc_stack.append(current)

    current_scc_set = set()
    for adj in adj_table[current]:
        if isinf(disc[adj]):
            Tarjan(adj, low, disc, scc_stack, in_scc_stack)
            low[current] = min(low[current], low[adj])

        elif in_scc_stack[adj]:
            low[current] = min(low[current], disc[adj])

    scc_candidate = -1
    if disc[current] == low[current]:
        while scc_candidate != current:
            scc_candidate = scc_stack.pop()
            current_scc_set.add(scc_candidate)
            in_scc_stack[scc_candidate] = False

        init_scc_sets_list.append(current_scc_set)

    return None


def scc():
    disc = [float('inf')] * vertices
    low = [float('inf')] * vertices
    scc_stack = list()
    in_scc_stack = [False] * vertices

    for v in range(vertices):
        if isinf(disc[v]):
            Tarjan(v, low, disc, scc_stack, in_scc_stack)

    return init_scc_sets_list


def solve():
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in scc_sets_list:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    timer = 0
    init_scc_sets_list = []
    scc_sets_list = scc()
    solve()

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""

import sys
from math import isinf

sys.setrecursionlimit(int(1e5))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def Tarjan(current, low, dfn, scc_stack, in_scc_stack):
    global timer
    dfn[current] = low[current] = timer
    timer += 1

    scc_stack.append(current)
    in_scc_stack[current] = True

    current_scc_set = set()
    for adj in adj_table[current]:
        if isinf(dfn[adj]):
            Tarjan(adj, low, dfn, scc_stack, in_scc_stack)
            low[current] = min(low[current], low[adj])

        elif in_scc_stack[adj]:
            low[current] = min(low[current], dfn[adj])

    scc_candidate = -1
    if dfn[current] == low[current]:
        while scc_candidate != current:
            scc_candidate = scc_stack.pop()
            in_scc_stack[scc_candidate] = False
            current_scc_set.add(scc_candidate)

        init_scc_sets_list.append(current_scc_set)

    return None


def scc_cluster():
    dfn = [float('inf')] * vertices
    low = [float('inf')] * vertices
    scc_stack = list()
    in_scc_stack = [False] * vertices

    for v in range(vertices):
        if isinf(dfn[v]):
            Tarjan(v, low, dfn, scc_stack, in_scc_stack)

    return init_scc_sets_list


def solve(_scc_sets_list):
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in _scc_sets_list:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    timer = 0
    init_scc_sets_list = []
    scc_sets_list = scc_cluster()

    solve(scc_sets_list)

Solution (Python):



"""
input:
5 6
0 1
1 0
1 2
2 4
4 3
3 2
4
0 1
0 3
2 3
3 4

output:
1
0
1
1
"""

import sys
from math import isinf

sys.setrecursionlimit(int(1e5))


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
    return init_adj_table


def Tarjan(current, low, dfn, scc_stack, in_scc_stack):
    global timer
    dfn[current] = low[current] = timer
    timer += 1

    scc_stack.append(current)
    in_scc_stack[current] = True

    current_scc_set = set()
    for adj in adj_table[current]:
        if isinf(low[adj]):
            Tarjan(adj, low, dfn, scc_stack, in_scc_stack)
            low[current] = min(low[current], low[adj])

        elif in_scc_stack[adj]:
            low[current] = min(low[current], dfn[adj])

    scc_candidate = -1
    if dfn[current] == low[current]:
        while scc_candidate != current:
            scc_candidate = scc_stack.pop()
            in_scc_stack[scc_candidate] = False
            current_scc_set.add(scc_candidate)

        init_scc_sets_list.append(current_scc_set)

    return None


def scc_cluster():
    dfn = [float('inf')] * vertices
    low = [float('inf')] * vertices
    scc_stack = list()
    in_scc_stack = [False] * vertices

    for v in range(vertices):
        if isinf(low[v]):
            Tarjan(v, low, dfn, scc_stack, in_scc_stack)

    return init_scc_sets_list


def solve(_scc_sets_list):
    for question in q_list:
        flag = False
        ele1, ele2 = map(int, question)
        for each in _scc_sets_list:
            if (ele1 in each) and (ele2 in each):
                flag = True
                break
        if flag:
            print('1')
        else:
            print('0')

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:edges + 1])
    q_num = int(_input[edges + 1])
    q_list = map(lambda x: x.split(), _input[edges + 2:])

    init_adj_table = tuple([] for _ in range(vertices))
    adj_table = generate_adj_table(v_info)

    timer = 0
    init_scc_sets_list = []
    scc_sets_list = scc_cluster()

    solve(scc_sets_list)