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 C++ (judge verdict: Accepted)

//強連結成分分解
//O(V + E)
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
#define MAX_V 100010
 
int V, E;                                       //頂点数　辺数
vector<int> G[MAX_V];                           //グラフの隣接リスト表現(0-indexed)
vector<int> rG[MAX_V];                          //辺の向きを逆向きにしたグラフ
vector<int> vs;                                 //帰りがけ順での頂点の並び
bool used[MAX_V];                               //dsfのために、すでに訪れたかどうかを管理する
int cmp[MAX_V];                                 //属する強連結成分のトポロジカル順序
 
void dfs(int v){
 
    used[v] = true;
    for(int i = 0; i < (int)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 < (int)rG[v].size(); i++){
        if(!used[rG[v][i]]) rdfs(rG[v][i], k);
    }
}
 
int scc(){
    memset(used, false, sizeof(used));
    vs.clear();
    for(int v = 0; v < V; v++){
        if(!used[v]) dfs(v);
 
    }
    memset(used, false, sizeof(used));
    int k = 0;
    for(int i = V - 1; i >= 0; i--){
        if(!used[vs[i]]){
            rdfs(vs[i], k);
            k++;
        }
    }    
    return k;
}
 
int main(){
 
    //入力
    cin >> V >> E;                              //頂点数　辺数
     
    for(int i = 0; i < E; i++){
        int from, to; cin >> from >> to;        //from -> toへの有向辺
        G[from].push_back(to); 
        rG[to].push_back(from);
    }
 
    memset(used, false, sizeof(used));
    scc();
     
    int Q; cin >> Q;
    for(int i = 0; i < Q; i++){
        int u, v; cin >> u >> v;
        cout << (cmp[u] == cmp[v]) << endl;
    }
    return 0;
}