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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;
// #include "all.h"

#define int long long
#define uint unsigned int
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define is2pow(n) (n && (!(n & (n - 1))))
#define OPTIMIZE                                                                                                       \
    ios_base::sync_with_stdio(false);                                                                                  \
    cin.tie(nullptr);                                                                                                  \
    cout.tie(nullptr);

using ld = long double;
constexpr int maxn = 2e5;
constexpr int maxk = 305;
constexpr long long inf = 1e18;
constexpr ld eps = 1e-8L;
constexpr long long mod = 998244353;

vector<vector<int>> graph;
vector<vector<int>> reversed;
vector<int> comp;

void solve() {
    int n,m; cin >> n >> m;
    graph.assign(n, vector<int>());
    reversed.assign(n, vector<int>());
    comp.assign(n,0);
    for (int i = 0; i < m; i++) {
        int u,v; cin >> u >> v;
        graph[u].push_back(v);
        reversed[v].push_back(u);
    }

    vector<int> visited(n,0);
    vector<int> order;

    auto topsort = [&](auto&& self, int u) -> void {
        visited[u] = 1;
        for (int v : graph[u])
            if (!visited[v])
                self(self,v);
        order.push_back(u);
    };
    for (int i = 0; i < n; i++) {
        if (!visited[i])
            topsort(topsort,i);
    }
    reverse(all(order));
    visited.assign(n,0);

    int color = 1;

    for (auto v : order) {
        if (visited[v]) continue;

        auto dfs = [&](auto&& self, int u) -> void {
            visited[u] = 1;
            comp[u] = color;
            for (auto to : reversed[u])
                if (!visited[to])
                    self(self,to);
        };

        dfs(dfs,v);
        color++;
    }







    int q; cin >> q;
    while (q--) {
        int u,v; cin >> u >> v;
        cout << (comp[u] == comp[v]) << "\n";
    }

}

#define TES
#define LOCA
#define FIL

int32_t main() {
    OPTIMIZE;

#ifdef FILE
    freopen("coins.in", "r", stdin);
    freopen("coins.out", "w", stdout);
#endif
#ifdef LOCAL
    freopen("/home/sq/CLionProjects/graph/input.txt", "r", stdin);
#endif
    int tt = 1;
#ifdef TEST
    cin >> tt;
#endif
    while (tt--) {
        solve();
    }
}
accuracy: 1
time_ms: 10
memory_kb: 5464
final_rank: 3

code_snippet: #include<iostream>
#include<vector>

using namespace std;
using Graph = vector<vector<int>>;

int n;
Graph g;

void Graph_rev(){
	Graph tmp(n);
	for(int i = 0; i < n; i++){
		for(auto j : g[i]) tmp[j].push_back(i);
	}
	g = tmp;
}

vector<int> group, ended;
vector<bool> view;

void dfs1(int f){
	view[f] = true;
	for(auto i : g[f]){
		if(!view[i]) dfs1(i);
	}
	ended.push_back(f);
}

void dfs2(int f, int num){
	group[f] = num;
	for(auto i : g[f]){
		if(group[i] == -1) dfs2(i, num);
	}
}

void scc(){
	view.assign(n, false);
	ended.clear();
	for(int i = 0; i < n; i++){
		if(!view[i]) dfs1(i);
	}
	Graph_rev();
	group.assign(n, -1);
	for(int i = n - 1, gn = 0; i >= 0; i--){
		if(group[ended[i]] == -1) dfs2(ended[i], gn++);
	}
}

int main(){
	int E;
	cin >> n >> E;
	g = Graph(n);
	int s, t;
	while(E--){
		cin >> s >> t;
		g[s].push_back(t);
	}
	scc();
	int Q;
	cin >> Q;
	while(Q--){
		cin >> s >> t;
		if(group[s] == group[t]) cout << 1 << endl;
		else cout << 0 << endl;
	}
}
accuracy: 1
time_ms: 60
memory_kb: 5120
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;

struct Scc{
  vector<vector<int>> G,H;
  vector<int> T,ord,seq,vis;
  int N,timer,sz;
  Scc(int n):N(n),G(n),H(n),vis(n),T(n,-1),timer(0),ord(n,-1),sz(1),seq(n){
    for(int i=0;i<N;i++) seq[i]=i;
  }
  void add(int u,int v){
    G[u].push_back(v);
    H[v].push_back(u);
  }
  vector<vector<int>> scc(){
    timer = 0;
    for(int i=0;i<N;i++) if(T[i]==-1) dfs1(i,-1);

    sort(seq.begin(),seq.end(),[&](auto a,auto b){
      return T[a]>T[b];
    });


    vector<vector<int>> ret;

    for(int i=0;i<N;i++) if(ord[seq[i]]==-1){
      vector<int> tmp;
      dfs2(tmp,seq[i],-1);
      ret.push_back(tmp);
      sz++;
    }

    return ret;
  }
private:
  void dfs1(int v,int par){
    vis[v]=1;
    for(auto nv : G[v]) if(nv!=par&&!vis[nv]) {
      dfs1(nv,v);
    }
    T[v] = timer++;
  }
  void dfs2(vector<int> &ret,int v,int par){
    ord[v] = sz;
    for(auto nv : H[v]) if(nv!=par&&ord[nv]==-1){
      dfs2(ret,nv,v);
    }
    ret.push_back(v);
  }
};


int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  int N,M;
  cin>>N>>M;
  Scc scc(N);
  for(int i=0;i<M;i++){
    int a,b;
    cin>>a>>b;
    scc.add(a,b);
  }
  auto vvec = scc.scc();
  int Q;
  cin>>Q;
  while(Q--){
    int u,v;
    cin>>u>>v;
    cout << int(scc.ord[u]==scc.ord[v]) << endl;
  }

}
accuracy: 1
time_ms: 70
memory_kb: 5148
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define YES cout<<"Yes"<<endl
#define NO cout<<"No"<<endl
using ll=long long;
using pi=pair<int,int>;
const int di[]={+1,-1,+0,+0};
const int dj[]={+0,+0,+1,-1};
const int INF=1e9;
//const ll INF=1e18;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<vector<int>> G(n), rG(n);
    rep(i, m) {
        int s, t;
        cin >> s >> t;
        G[s].push_back(t);
        rG[t].push_back(s);
    }
    vector<bool> seen(n, false);
    vector<int> order;
    auto dfs=[&](auto dfs, int v) -> void {
        seen[v]=true;
        for(int nv:G[v]) if(!seen[nv]) {
            dfs(dfs, nv);
        }
        order.push_back(v);
    };
    rep(i, n) if(!seen[i]) {
        dfs(dfs, i);
    }
    vector<int> comp(n, -1);
    auto rdfs=[&](auto rdfs, int v, int id) -> void {
        comp[v]=id;
        for(int nv:rG[v]) if(comp[nv]==-1) {
            rdfs(rdfs, nv, id);
        }
    };
    int cnt=0;
    reverse(all(order));
    for(int v:order) if(comp[v]==-1) {
        rdfs(rdfs, v, cnt);
        cnt++;
    }
    int q; cin >> q;
    vector<int> ans;
    while(q--) {
        int u, v; cin >> u >> v;
        ans.push_back(comp[u]==comp[v] ? 1:0);
    }
    for(int x:ans) cout << x << endl;

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 5632
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <stack>

const int MAXN =  10000 + 1;

std::vector<int> G[MAXN];
std::vector<int> RG[MAXN];
std::stack<int> reverse_post;
bool visited[MAXN];
int scc[MAXN];
int count = 0;
bool record_scc = false;

void dfs(std::vector<int> g[], int v)
{
    visited[v] = true;
    if (record_scc) scc[v] = count;
    for (int i = 0; i < g[v].size(); ++i) {
        if (!visited[g[v][i]]) {
            dfs(g, g[v][i]);
        }
    }
    reverse_post.push(v);
}

int main()
{
    int v, e;
    std::cin >> v >> e;
    for (int i = 0; i < e; ++i) {
        int s, t;
        std::cin >> s >> t;
        G[s].push_back(t);
        RG[t].push_back(s);
    }
    for (int i = 0; i < v; ++i) {
        if (!visited[i]) {
            dfs(RG, i);
        }
    }
    for (int i = 0; i < v; ++i) {
        visited[i] = false;
    }
    record_scc = true;
    while (!reverse_post.empty()) {
        int v = reverse_post.top();
        reverse_post.pop();
        if (!visited[v]) {
            dfs(G, v);
            count++;
        }
    }

    int q;
    std::cin >> q;
    while (q--) {
        int u, v;
        std::cin >> u >> v;
        if (scc[u] == scc[v]) std::cout << 1;
        else std::cout << 0;
        std::cout << std::endl;
    }

    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5020
final_rank: 11

code_snippet: #include <iostream>
#include <vector>

using namespace std;

#define MAX 10010
vector<int> edge[MAX], group[MAX];
bool instk[MAX];
int stk[MAX], groupID[MAX], nGroup, dfn[MAX], low[MAX], top, nowDfn;
void tarjan(int start)
{
    dfn[start] = low[start] = ++nowDfn;
    instk[start] = 1;
    stk[top++] = start;
    for(int i = 0; i < edge[start].size(); ++i){
        int next = edge[start][i];
        if(!dfn[next]){
            tarjan(next);
            if(low[start] > low[next])
                low[start] = low[next];
        }
        if(instk[next])
            if(low[start] > dfn[next])
                low[start] = dfn[next];
    }
    if(dfn[start] == low[start]){
        do {
            --top;
            instk[stk[top]] = 0;
            groupID[stk[top]] = nGroup;
            group[nGroup].push_back(stk[top]);
        } while(stk[top] != start);
        ++nGroup;
    }
}
void init(int n){
    for(int i = 0; i < n; ++i){
        instk[i] = dfn[i] = 0, edge[i].clear(), group[i].clear();
    }
    nowDfn = nGroup = top = 0;
}

int main()
{
    int V, E;
    cin >> V >> E;
    init(V);
    int s, t;
    for(int i = 0; i < E; ++i){
        cin >> s >> t;
        edge[s].push_back(t);
    }
    for(int i = 0; i < V; ++i){
        if(dfn[i] == 0) tarjan(i);
    }
    int q;
    cin >> q;
    int u, v;
    for(int i = 0; i < q; ++i){
        cin >> u >> v;
        cout << (groupID[u] == groupID[v]) << '\n';
    }
}
accuracy: 1
time_ms: 90
memory_kb: 4924
final_rank: 10

code_snippet: #pragma once
#include <bits/stdc++.h>
using namespace std;


struct Edge {
    int from;
    int to;
    int weight;
    int capacity{};
    int flow{};
    int index{};
    Edge(int from, int to, int weight) : from(from), to(to), weight(weight) {}
    bool operator>(const Edge& other) const {
        return weight > other.weight;
    }
};

struct SCC {
    // Finds strongly connected components in a directed graph using Kosaraju's algorithm
    // Time: O(n + m)
    // Space: O(n + m)
    // Strongly Connected Components https://judge.yosupo.jp/submission/311149
    vector<vector<Edge>> graph;
    vector<vector<Edge>> reversedGraph;
    vector<int> comp; // comp[v] - component index for vertex v
    vector<vector<int>> components;
    int vertexCount{};

    explicit SCC(int vertexCount) : vertexCount(vertexCount) {
        graph.resize(vertexCount);
        reversedGraph.resize(vertexCount);
        comp.resize(vertexCount);
        components.reserve(vertexCount);
    }

    void addEdge(int from, int to, int weight = 1) {
        graph[from].emplace_back(from, to, weight);
        reversedGraph[to].emplace_back(to, from, weight);
    }

    vector<vector<int>> buildComponents() {
        vector<int> order(vertexCount);
        vector<int> visited(vertexCount, false);
        auto topologicalSort = [&](auto&& topSort, int start = 0) -> void {
            visited[start] = true;
            for (Edge edge : graph[start])
                if (!visited[edge.to])
                    topSort(topSort, edge.to);
            order.push_back(start);
        };
        for (int i = 0; i < vertexCount; i++)
            if (!visited[i])
                topologicalSort(topologicalSort, i);

        visited.assign(vertexCount, false);
        comp.assign(vertexCount, -1);
        int compId = 0;
        for (int i = order.size() - 1; i >= 0; i--) {
            if (!visited[order[i]]) {
                // Traverse the vertices in reverse topological order, through edges that point into the current vertex
                // One way to do that is using reversed graph
                auto dfsRev = [&](auto&& dfs, int start) -> void {
                    visited[start] = true;
                    comp[start] = compId;
                    components.back().push_back(start);
                    for (Edge edge : reversedGraph[start])
                        if (!visited[edge.to])
                            dfs(dfs, edge.to);
                };
                components.emplace_back();
                dfsRev(dfsRev, order[i]);
                compId++;
            }
        }
        return components;
    }

    vector<vector<Edge>> condense() {
        int componentCount = components.size();
        vector<vector<Edge>> condensedGraph(componentCount);
        vector<unordered_set<int>> usedEdges(componentCount);
        for (int from = 0; from < vertexCount; from++) {
            for (Edge edge : graph[from]) {
                int to = edge.to;
                if (comp[from] != comp[to] && !usedEdges[comp[from]].count(comp[to])) {
                    Edge condensedEdge(comp[from], comp[to], edge.weight);
                    condensedGraph[comp[from]].push_back(condensedEdge);
                    usedEdges[comp[from]].insert(comp[to]);
                }
            }
        }
        return condensedGraph;
    }
};

int main() {
    // SCC
    int n, m;
    cin >> n >> m;

    SCC scc(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        scc.addEdge(u, v);
    }

    auto components = scc.buildComponents();
    int q; cin >> q;
    while (q--) {
        int u, v;
        cin >> u >> v;
        cout << (scc.comp[u] == scc.comp[v]) << endl;
    }

}
accuracy: 1
time_ms: 90
memory_kb: 5760
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pll = pair<ll, ll>;
using int128 = __int128;
using State = string::const_iterator;
class ParseError {};
#define rep(i, n) for(ll i = 0; i < (n); i++)
#define reps(i, l, r) for(ll i = (l); i < (r); i++)
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define endl "\n";
const ll INF = LLONG_MAX / 4;
const ld inf = numeric_limits<long double>::max() / (ld)4;
const ll mod1 = 1000000007;
const ll mod2 = 998244353;
const ld pi = 3.1415926535897;
ll dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
ll dy[8] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T>
bool chmax(T &a, const T& b) {
	if (a < b) { a = b; return true; }
	return false;
}
template <typename T>
bool chmin(T &a, const T &b) {
	if (a > b) { a = b; return true; }
	return false;
}
struct Edge {
	ll from, to, cost;
	Edge (ll from, ll to, ll cost = 1ll) : from(from), to(to), cost(cost) {}
};
struct Graph {
	vector<vector<Edge>> G;
	Graph() = default;
	explicit Graph(ll N) : G(N) {}
	size_t size() const {
		return G.size();
	}
	void add(ll from, ll to, ll cost = 1ll, bool direct = 0) {
		G[from].emplace_back(from, to, cost);
		if (!direct) G[to].emplace_back(to, from, cost);
	}
	vector<Edge> &operator[](const int &k) {
		return G[k];
	}
};
using Edges = vector<Edge>;
struct SCC {
	Graph &g;
	Graph gg, rg;
	vector<ll> cmp, ord, use;

	SCC(Graph &g): g(g), gg(g.size()), rg(g.size()), cmp(g.size(), -1), use(g.size()) {
		rep(i, g.size()) {
			for (auto e : g[i]) {
				gg.add(i, e.to, 1, 1);
				rg.add(e.to, i, 1, 1);
			}
		}
	}

	ll operator[](ll k) { return cmp[k]; }

	void dfs(ll p) {
		if (use[p]) return;
		use[p] = 1;
		for (auto e : gg[p]) dfs(e.to);
		ord.push_back(p);
	}

	void rdfs(ll p, ll cnt) {
		if (cmp[p] != -1) return;
		cmp[p] = cnt;
		for (auto e : rg[p]) rdfs(e.to, cnt);
	}

	void build(Graph &t) {
		rep(i, gg.size()) {
			dfs(i);
		}
		reverse(all(ord));
		ll ptr = 0;
		for (ll i : ord) {
			if (cmp[i] == -1) rdfs(i, ptr), ptr++;
		}

		t = Graph(ptr);
		rep(i, g.size()) {
			for (auto &e : g[i]) {
				ll x = cmp[i], y = cmp[e.to];
				if (x == y) continue;
				t.add(x, y, 1, 1);
			}
		}
	}
};
void solve() {
	ll V, E; cin >> V >> E;
	Graph G(V);
	rep(i, E) {
		ll s, t; cin >> s >> t;
		G.add(s, t, 1, 1);
	}
	SCC scc(G);
	Graph T;
	scc.build(T);
	ll Q; cin >> Q;
	while (Q--) {
		ll x, y; cin >> x >> y;
		cout << (scc[x] == scc[y]) << endl;
	}
}
int main() {
	ll T = 1;
	// cin >> T;
	while (T--) {
		solve();
	}
}
accuracy: 1
time_ms: 90
memory_kb: 6428
final_rank: 19

code_snippet: // nur_008
// بِسْمِ اللَّهِ الرَّحْمَـٰنِ الرَّحِيمِ
#include <bits/stdc++.h>
using namespace std;
using ll = long long int;

void champ()
{
    int V, E;
    cin >> V >> E;
    vector<vector<int>> g(V), rg(V);
    for (int i = 0; i < E; i++) {
        int s, t;
        cin >> s >> t;
        g[s].push_back(t);
        rg[t].push_back(s);
    }

    vector<int> order, comp(V, -1);
    vector<bool> vis(V, false);

    function<void(int)> dfs1 = [&](int u) {
        vis[u] = true;
        for (int v : g[u]) if (!vis[v]) dfs1(v);
        order.push_back(u);
    };

    function<void(int,int)> dfs2 = [&](int u, int cid) {
        comp[u] = cid;
        for (int v : rg[u]) if (comp[v] == -1) dfs2(v, cid);
    };

    for (int i = 0; i < V; i++) if (!vis[i]) dfs1(i);
    reverse(order.begin(), order.end());

    int cid = 0;
    for (int u : order) if (comp[u] == -1) dfs2(u, cid++);

    int Q;
    cin >> Q;
    while (Q--) {
        int u, v;
        cin >> u >> v;
        cout << (comp[u] == comp[v] ? 1 : 0) << "\n";
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    // cin >> t;
    while (t--) champ();
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4880
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = (1 << 30);

vector<int> group, order;
vector<vector<int>> g, gt;
vector<bool> visited;
int v, e, t;


void dfs1(int u) {
    assert(u >= 0);
    visited[u] = true;
    for(auto && _v: g[u]) {
        if (!visited[_v]) {
            dfs1(_v);
        }
    }
    order.push_back(u);
}

void dfs2(int u) {
    assert(u >= 0);
    group[u] = t;
    for(auto && _v: gt[u]) {
        if (group[_v] == -1) dfs2(_v);
    }
}

signed main() {
    cin >> v >> e;
    g.assign(v, vector<int> ());
    gt.assign(v, vector<int> ());
    group.assign(v, -1);
    visited.assign(v, false);

    for (int i = 0; i < e; i++)
    {
        int _s, _t;
        cin >> _s >> _t;
        g[_s].push_back(_t);
        gt[_t].push_back(_s);

    }
    for (int i = 0; i < v; i++)
    {
        if (!visited[i]) dfs1(i);
    }
    
    for (int i = v-1; i>=0; i--) {
        int _v = order[i];
        if (group[_v] == -1) {
            dfs2(_v);
            t++;
        }
    }
    int q;
    cin >> q;
    for (int i = 0; i < q; i++)
    {
        int _u, _v;
        cin >> _u >> _v;
        if (group[_u] == group[_v]) cout << 1 << endl;
        else cout << 0 << endl;
    }
}
accuracy: 1
time_ms: 100
memory_kb: 5008
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define ll long long int
#define X first
#define Y second

struct SCC
{
    int n, cnt, dfs_num;
    vector<vector<int>> adj, dagList;
    vector<int> inStack, lowLink, dfn, comp;
    stack<int> st;
    vector<vector<int>> scc;
    vector<int> artipoints;

    vector<pair<int, int>> ciriticalEdges;

    stack<pair<int, int>> bi_comps;

    bool root = false;

    SCC(int n)
        : n(n), cnt(0), adj(n), inStack(n), lowLink(n), dfn(n, -1), comp(n, -1), dfs_num(0)
    {
        artipoints.assign(n, 0);
    }

    void add_edge(int u, int v)
    {
        adj[u].push_back(v);
    }

    void dfs(int node)
    {
        inStack[node] = 1;
        for (auto &child : dagList[node])
        {
            if (!inStack[child])
            {
                dfs(child);
            }
        }
    }

    void tarjan(int node, int parent = -1)
    {
        lowLink[node] = dfn[node] = dfs_num++, inStack[node] = 1;
        st.push(node);
        int to_parent = 0;
        for (auto &child : adj[node])
        {
            if (child == parent and to_parent == 0)
            {
                to_parent = 1;
                continue;
            }
            if (dfn[child] == -1)
            {
                tarjan(child);
                lowLink[node] = min(lowLink[node], lowLink[child]);
                if ((lowLink[child] >= dfn[node]) and (dfn[node] or root))
                {
                    artipoints[node] = 1;
                }
                if (dfn[node] == 0 and root == false)
                {
                    root = true;
                }
            }
            else if (inStack[child])
            {
                lowLink[node] = min(lowLink[node], dfn[child]);
            }
        }
        if (lowLink[node] == dfn[node])
        {
            if (parent != -1)
            {
                ciriticalEdges.push_back({parent, node});
            }
            scc.push_back({});
            while (true)
            {
                int v = st.top();
                st.pop();
                inStack[v] = 0;
                scc.back().push_back(v);
                comp[v] = cnt;
                if (v == node)
                    break;
            }
            cnt++;
        }
    }

    void get_dag_list()
    {
        dagList.resize(cnt);
        for (int i = 0; i < n; i++)
        {
            for (auto &child : adj[i])
            {
                if (comp[i] != comp[child])
                {
                    dagList[comp[i]].push_back(comp[child]);
                }
            }
        }
    }

    void run()
    {
        for (int i = 0; i < n; i++)
        {
            if (dfn[i] == -1)
            {
                tarjan(i);
            }
        }
    }
};

/*
@Problems:
https://www.spoj.com/problems/EC_P/
https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/3/GRL_3_B
*/

void solve()
{
    int n, m;
    cin >> n >> m;
    SCC scc(n);
    for (int i = 0; i < m; i++)
    {
        int u, v;
        cin >> u >> v;
        scc.add_edge(u, v);
    }
    scc.run();
    int q;
    cin >> q;
    while (q--)
    {
        int u, v;
        cin >> u >> v;
        cout << (scc.comp[u] == scc.comp[v]) << '\n';
    }
}

int main()
{
    ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
#ifdef LOCAL_IO
    freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#endif
    int tc = 1;
    // cin >> tc;
    for (int i = 1; i <= tc; ++i)
    {
        solve();
    }
}
accuracy: 1
time_ms: 10
memory_kb: 5172
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#include <vector>
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,r,n) for(int i=(r);i<(n);i++)
#define ALL(obj) begin(obj),end(obj)
template<typename T> bool chmin(T &a,T b){
    if (a>b) {
        a=b;
        return true;
    }
    else return false;
}
using namespace std;
typedef long long ll;
typedef vector<vector<int>> vvi; 
struct StronglyConnectedComponent{
    int N;
    vvi G,rG;
    vector<int> ord,vis,comp;

    void dfs(int v){
        vis[v]=1;
        for(auto u:G[v]) if (!vis[u]) dfs(u);
        ord.push_back(v);
    }
    void rdfs(int v,int k){
        comp[v]=k;
        for(auto u:rG[v]) if (comp[u]==-1) rdfs(u,k);
    }
    StronglyConnectedComponent(vvi &_G){
        G=_G;
        int N=G.size();
        rG.resize(N);  
        comp.assign(N,-1);
        vis.assign(N,0);
        REP(i,N) {
            for(auto u:G[i]) rG[u].push_back(i);
        }
        REP(i,N) if (!vis[i]){
            dfs(i);
        }
        int k=0;
        reverse(ALL(ord));
        for(auto v:ord) if (comp[v]==-1) {
            rdfs(v,k);
            k++;
        }
    }
    bool same(int u,int v){
        if (comp[u]==comp[v]) return 1;
        else return 0;
    }
};
int main(){
    int N,M,Q;
    cin >> N >> M;
    vvi G(N);
    REP(i,M) {
        int a,b;
        cin >> a >> b;
        G[a].push_back(b);
    }
    StronglyConnectedComponent SCC(G);
    cin >> Q;
    REP(_,Q){
        int a,b;
        cin >> a >> b;
        cout <<SCC.same(a,b)<<endl;
    }
}
accuracy: 1
time_ms: 90
memory_kb: 5512
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#include <vector>
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,r,n) for(int i=(r);i<(n);i++)
#define ALL(obj) begin(obj),end(obj)
template<typename T> bool chmin(T &a,T b){
    if (a>b) {
        a=b;
        return true;
    }
    else return false;
}
using namespace std;
typedef long long ll;
typedef vector<vector<int>> vvi; 
struct StronglyConnectedComponents{
    int n;
    vvi G,rG;
    vector<int> ord,vis,comp;
    void dfs(int v){
        vis[v]=1;
        for(auto u:G[v]) if (!vis[u]) dfs(u);
        ord.push_back(v);
    }
    void rdfs(int v,int k){
        comp[v]=k;
        for(auto u:rG[v]) if (comp[u]==-1){
            rdfs(u,k);
        }
    }
    StronglyConnectedComponents(vvi &_G){
        G=_G;
        n=G.size();
        rG.resize(n);
        REP(i,n){
            for(auto u:G[i]) rG[u].push_back(i);
        }
        vis.assign(n,0);
        REP(i,n) if (!vis[i]) dfs(i);
        reverse(ALL(ord));
        comp.assign(n,-1);
        int k=0;
        REP(i,n) if (comp[ord[i]]==-1) {
            rdfs(ord[i],k);
            k++;
        }
    }   
};
int main(){
    int N,M,Q;
    cin >> N >> M;
    vvi G(N);
    REP(i,M){
        int a,b;
        cin >> a >> b;
        G[a].push_back(b);
    }
    StronglyConnectedComponents SCC(G);
    cin >> Q;
    REP(i,Q){
        int u,v;
        cin >> u >> v;
        if (SCC.comp[u]==SCC.comp[v]) cout << 1 << endl;
        else cout << 0 << endl;
    }
}
accuracy: 1
time_ms: 90
memory_kb: 5492
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>

std::vector<std::vector<int>> G, rG;
std::vector<bool> visited;
std::vector<int> order;
std::vector<int> component;

void dfs(int u){
  visited[u] = true;

  for(int v : G[u]){
    if(!visited[v]){
      dfs(v);
    }
  }
  order.push_back(u);
}

void rdfs(int u, int k){
  visited[u] = true;
  component[u] = k;
  for(int v : rG[u]){
    if(!visited[v]){
      rdfs(v, k);
    }
  }
}

int main(){
  int v, e;
  std::cin >> v >> e;

  G.resize(v);
  rG.resize(v);
  
  for(int i=0;i<e;i++){
    int u,w;
    std::cin >> u >> w;
    G[u].push_back(w);
    rG[w].push_back(u);
  }

  visited.assign(v, false);
  for(int i=0;i<v;i++) {
    if(!visited[i]){
      dfs(i);
    }
  }

  visited.assign(v, false);
  component.resize(v);
  int scc_id = 0;
  for(int i=v-1;i>=0;i--) {
    int u = order[i];
    if(!visited[u]){
      rdfs(u, scc_id);
      scc_id++;
    }
  }

  int q;
  std::cin >> q;
  for(int i=0;i<q;i++){
    int u,w;
    std::cin >> u >> w;

    if(component[u] == component[w]){
      std::cout << 1 << std::endl;
    }else{
      std::cout << 0 << std::endl;
    }
  }
  
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 4900
final_rank: 9

code_snippet: // GRL_3_C
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;

using Graph = vector<vector<int>>;
Graph G, rG;

vector<bool> seen;
vector<int> st;
vector<int> comp;
int cid = 0;

void DFS1(int u) {
    seen[u] = true;
    for(auto& next : G[u]) {
        if(!seen[next]) DFS1(next);
    }
    st.push_back(u);
}

void DFS2(int u) {
    comp[u] = cid;
    for(auto& next : rG[u]) {
        if(comp[next] < 0) DFS2(next);
    }
}

int main() {
    int V, E;
    cin >> V >> E;
    G.resize(V);
    rG.resize(V);
    for(int i=0; i<E; ++i) {
        int s, t;
        cin >> s >> t;
        G[s].push_back(t);
        rG[t].push_back(s);
    }

    seen.assign(V, false);
    st.reserve(V);
    comp.assign(V, -1);

    for(int u=0; u<V; ++u) {
        if(!seen[u]) DFS1(u);
    }

    for(int i=V-1; i >= 0; --i) {
        int u = st[i];
        if(comp[u] < 0) {
            DFS2(u);
            cid++;
        }
    }

    int q;
    cin >> q;
    for(int i=0; i<q; ++i) {
        int u, v;
        cin >> u >> v;
        if(comp[u] == comp[v]) {
            cout << 1 << endl;
        }
        else cout << 0 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 4560
final_rank: 13

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

vector<vector<int>> G; //グラフ
vector<vector<int>> GT; //転置グラフ
vector<int> visited;
vector<int> order; // 終了順に格納する
vector<vector<int>> scc; 
// sccごとの集合で表示する

vector<int> node_to_comp;
// nodeの所属するのはどこか？

void dfs(int u){
    visited[u] = 1;
    for(int i=0;i<G[u].size();i++){
        int v = G[u][i];
        if(!visited[v]){
            dfs(v);
        }
    }
    order.push_back(u);
}

void dfs_T(int u, vector<int>& component){
    visited[u] = 1;
    component.push_back(u);
    for(int i=0;i<GT[u].size();i++){
        int v = GT[u][i];
        if(!visited[v]){
            dfs_T(v, component);
        }
    }
}

bool sameComp(int a,int b){
    return node_to_comp[a] == node_to_comp[b];
}

int main(){
    int V,E;
    int s,t;
    int Q,x,y;

    cin >> V >> E;
    G.resize(V);
    GT.resize(V);
    node_to_comp.resize(V,-1);
    visited.resize(V,0);

    for(int i=0;i<E;i++){
        cin >> s >> t;
        G[s].push_back(t);
        GT[t].push_back(s);
    }

    for(int i=0;i<V;i++){
        if(!visited[i]){
            //訪問していないすべてを見るから
            dfs(i);
        }
    }

    //visitedをリセットする
    for(int i=0;i<V;i++){
        visited[i] = 0;
    }

    reverse(order.begin(),order.end());
    //これで反転させる

    for(int i=0;i<order.size();i++){
        if(!visited[order[i]]){
            vector<int> comp; //sccの集合体を求める
            dfs_T(order[i], comp);

            // わかりやすくするためにソートする
            sort(comp.begin(), comp.end());
            scc.push_back(comp);
        }
    }

    // node_to_compの前処理
    for(int i=0;i<scc.size();i++){
        for(int j=0;j<scc[i].size();j++){
            int v = scc[i][j];
            node_to_comp[v] = i;
        }
    }

    //　クエリの処理をする
    cin >> Q;

    for(int i=0;i<Q;i++){
        cin >> x >> y;
        if(sameComp(x,y)){
            cout << 1 << endl;
        }else{
            cout << 0 << endl;
        }
    }

    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 4876
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lli=long long int;
using ld=long double;
using vi=vector<int>;
using vvi=vector<vi>;
using vvvi=vector<vvi>;
using vvvvi=vector<vvvi>;
using vl=vector<lli>;
using vvl=vector<vl>;
using vb=vector<bool>;
using vvb=vector<vb>;
#define rep(i,s,e) for(int i=s;i<e;i++)
#define leap(i,s,e,j) for(int i=s;i<e;i+=j)
#define repl(i,s,e) for(lli i=s;i<e;i++)
#define rrep(i,s,e) for(int i=s-1;i>=e;i--)
#define rleap(i,s,e,j) for(int i=s-1;i>=e;i-=j)
#define in(v,seq) for(auto v:seq)
#define veci(v,s) vi v(s); rep(i,0,s) cin >> v.at(i);
#define vecl(v,s) vl v(s); rep(i,0,s) cin >> v.at(i);
#define all(s) s.begin(),s.end()
#define rall(s) s.rbegin(),s.rend()
using pii=pair<int,int>;
using pll=pair<lli,lli>;
#define mp(f,s) make_pair(f,s)
#define fi first
#define se second
using vpii=vector<pii>;
using vpll=vector<pll>;
#define vecpii(v,s) vpii v(s); rep(i,0,s) cin >> v.at(i).fi >> v.at(i).se;
#define vecpll(v,s) vpll v(s); rep(i,0,s) cin >> v.at(i).fi >> v.at(i).se;
#define pub(x) push_back(x)
#define puf(x) push_front(x)
#define pob(x) pop_back(x)
#define pof(x) pop_front(x)
#define emb(x) emplace_back(x)
#define print(s) cout << s << endl;
#define ptp(p) cout << p.fi << " " << p.se << endl;
const int I_INF=1<<30;
const lli LL_INF=1ll<<60;
const string alp="abcdefghijklmnopqrstuvwxyz";
const int let=alp.size(); // 26

using SGraph=vector<vector<int>>;

vector<vector<int>> SCC(SGraph &G,SGraph &RG){
  int vertex=G.size();
  vector<int> rpost;
  vector<bool> seen(vertex,false);

  auto dfs=[&](auto &dfs,int v)->void{
    seen.at(v)=true;
    for(int nv:RG.at(v)){
      if(seen.at(nv)) continue;
      dfs(dfs,nv);
    }
    rpost.emplace_back(v);
    return;
  };

  for(int i=0;i<vertex;i++){
    if(seen.at(i)) continue;
    dfs(dfs,i);
  }

  seen.assign(vertex,false);
  vector<vector<int>> ret;
  int index=0;

  auto dfs_again=[&](auto &dfs_again,int v)->void{
    seen.at(v)=true;
    ret.at(index).emplace_back(v);
    for(int nv:G.at(v)){
      if(seen.at(nv)) continue;
      dfs_again(dfs_again,nv);
    }
    return;
  };

  for(int i=vertex-1;i>=0;i--){
    if(seen.at(rpost.at(i))) continue;
    ret.push_back({});
    dfs_again(dfs_again,rpost.at(i));
    index++;
  }

  return ret;
}

int main(){
  int vertex,edge; cin >> vertex >> edge;
  SGraph G(vertex),RG(vertex);
  rep(i,0,edge){
    int u,v; cin >> u >> v;
    G[u].pub(v);
    RG[v].pub(u);
  }

  auto c=SCC(G,RG);
  vi t(vertex,-1);
  rep(i,0,c.size()){
    in(v,c[i]) t[v]=i;
  }

  int q; cin >> q;
  rep(i,0,q){
    int u,v; cin >> u >> v;
    print((t[u]==t[v]));
  }
}
accuracy: 1
time_ms: 60
memory_kb: 5248
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define INF 0x7fffffff
#define MAXN 200010
typedef long long LL;
using namespace std;

int n, m, cnt, colcnt;
vector <int> g[MAXN];
int dfn[MAXN], low[MAXN], color[MAXN];
bool vis[MAXN];
stack <int> st;

void Tarjan(int u)
{
	dfn[u] = low[u] = ++cnt;
	st.push(u);
	vis[u] = true;
	for(int x = 0; x < g[u].size(); x++)
	{
		int v = g[u][x];
		if(!dfn[v])
		{
			Tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		colcnt++;
		int v;
		do
		{
			v = st.top(); st.pop();
			vis[v] = false;
			color[v] = colcnt;
		} while(v != u);
	}
}

int main()
{
	cin >> n >> m;
	for(int x = 1; x <= m; x++)
	{
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
	}
	for(int x = 0; x < n; x++)
		if(!dfn[x]) Tarjan(x);
	// for(int x = 0; x < n; x++) cout << color[x] << " ";
	// cout << endl;
	int q;
	cin >> q;
	while(q--)
	{
		int u, v;
		cin >> u >> v;
		cout << (color[u] == color[v]) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 9740
final_rank: 20

code_snippet: //
// 強連結成分分解
//
// verified:
//   Yosupo Judge - Strongly Connected Components
//     https://judge.yosupo.jp/problem/scc
//
//   AOJ Course GRL_3_C - 強連結成分分解
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_C&lang=ja
//


#include <bits/stdc++.h>
using namespace std;


// Edge Class
template<class T> struct Edge {
    int from, to;
    T val;
    Edge() : from(-1), to(-1), val(-1) { }
    Edge(int f, int t, T v = -1) : from(f), to(t), val(v) {}
    friend ostream& operator << (ostream& s, const Edge& E) {
        return s << E.from << "->" << E.to;
    }
};

// graph class
template<class T> struct Graph {
    vector<vector<Edge<T>>> list;
    vector<vector<Edge<T>>> reversed_list;
    
    Graph(int n = 0) : list(n), reversed_list(n) { }
    void init(int n = 0) {
        list.assign(n, vector<Edge<T>>());
        reversed_list.assign(n, vector<Edge<T>>());
    }
    const vector<Edge<T>> &operator [] (int i) const { return list[i]; }
    const vector<Edge<T>> &get_rev_edges(int i) const { return reversed_list[i]; }
    const size_t size() const { return list.size(); }
        
    void add_edge(int from, int to, T val = -1) {
        list[from].push_back(Edge(from, to, val));
        reversed_list[to].push_back(Edge(to, from, val));
    }
    
    void add_bidirected_edge(int from, int to, T val = -1) {
        list[from].push_back(Edge(from, to, val));
        list[to].push_back(Edge(to, from, val));
        reversed_list[from].push_back(Edge(from, to, val));
        reversed_list[to].push_back(Edge(to, from, val));
    }

    friend ostream &operator << (ostream &s, const Graph &G) {
        s << endl;
        for (int i = 0; i < G.size(); ++i) {
            s << i << " -> ";
            for (const auto &e : G[i]) s << e.to << " ";
            s << endl;
        }
        return s;
    }
};

// strongly connected components decomposition
template<class T> struct SCC {
    // results
    vector<int> cmp;
    vector<vector<int>> groups;
    Graph<T> dag;
    
    // intermediate results
    vector<bool> seen;
    vector<int> vs, rvs;
    
    // constructor
    SCC() { }
    SCC(const Graph<T> &G) { 
        solve(G);
    }
    void init(const Graph<T> &G) { 
        solve(G);
    }

    // getter, compressed dag（v: node-id of compressed dag)
    int get_size(int v) const {
        return groups[v].size();
    }
    vector<int> get_group(int v) const {
        return groups[v];
    }

    // solver
    void dfs(const Graph<T> &G, int v) {
        seen[v] = true;
        for (const auto &e : G[v]) if (!seen[e.to]) dfs(G, e.to);
        vs.push_back(v);
    }
    void rdfs(const Graph<T> &G, int v, int k) {
        seen[v] = true;
        cmp[v] = k;
        for (const auto &e : G.get_rev_edges(v)) if (!seen[e.to]) rdfs(G, e.to, k);
        rvs.push_back(v);
    }
    void reconstruct(const Graph<T> &G) {
        dag.init((int)groups.size());
        set<pair<int,int>> new_edges;
        for (int i = 0; i < (int)G.size(); ++i) {
            int u = cmp[i];
            for (const auto &e : G[i]) {
                int v = cmp[e.to];
                if (u == v) continue;
                if (!new_edges.count({u, v})) {
                    dag.add_edge(u, v);
                    new_edges.insert({u, v});
                }
            }
        }
    }
    void solve(const Graph<T> &G) {
        // first dfs
        seen.assign((int)G.size(), false);
        vs.clear();
        for (int v = 0; v < (int)G.size(); ++v) if (!seen[v]) dfs(G, v);

        // back dfs
        int k = 0;
        groups.clear();
        seen.assign((int)G.size(), false);
        cmp.assign((int)G.size(), -1);
        for (int i = (int)G.size()-1; i >= 0; --i) {
            if (!seen[vs[i]]) {
                rvs.clear();
                rdfs(G, vs[i], k++);
                groups.push_back(rvs);
            }
        }
        reconstruct(G);
    }
};



//------------------------------//
// Examples
//------------------------------//

void Yosupo_Strongly_Connected_Components() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    // 入力
    int N, M;
    cin >> N >> M;
    Graph<int> G(N);
    for (int i = 0; i < M; ++i) {
        int u, v;
        cin >> u >> v;
        G.add_edge(u, v);
    }
    //cout << G << endl;
    
    // SCC (not build dag)
    SCC<int> scc(G);
    const auto &groups = scc.groups;
    
    // 出力
    cout << groups.size() << endl;
    for (const auto &list : groups) {
        cout << list.size();
        for (auto v : list) cout << " " << v;
        cout << endl;
    }
}

void AOJ_GRL_3_C() {
    // 入力
    int N, M;
    cin >> N >> M;
    Graph<int> G(N);
    for (int i = 0; i < M; ++i) {
        int u, v;
        cin >> u >> v;
        G.add_edge(u, v);
    }
    
    // SCC
    SCC<int> scc(G);
    
    // クエリ
    int Q;
    cin >> Q;
    while (Q--) {
        int u, v;
        cin >> u >> v;
        if (scc.cmp[u] == scc.cmp[v]) cout << 1 << endl;
        else cout << 0 << endl;
    }
}


int main() {
    //Yosupo_Strongly_Connected_Components();
    AOJ_GRL_3_C();
}
accuracy: 1
time_ms: 90
memory_kb: 5200
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MAXN = 10005;

vector<int> G[MAXN];
vector<int> rG[MAXN];
vector<bool> vis(MAXN, false);
stack<int> st;
int id[MAXN];
int cnt = 0;

void dfs1(int u) {
	vis[u] = true;
	for (int v : G[u]) {
		if (!vis[v]) dfs1(v);
	}
	st.push(u);
}

void dfs2(int u) {
	vis[u] = true;
	id[u] = cnt;
	for (int v : rG[u]) {
		if (!vis[v]) dfs2(v);
	}
}

void kosaraju(int n) {
	for (int i = 0; i < n; ++i) {
		if (!vis[i]) dfs1(i);
	}
	vis.assign(n, false);
	while (!st.empty()) {
		int u = st.top(); st.pop();
		if (!vis[u]) {
			cnt++;
			dfs2(u);
		}
	}
}

int main() {
	int V, E;
	cin >> V >> E;
	while (E--) {
		int s, t;
		cin >> s >> t;
		G[s].push_back(t);
		rG[t].push_back(s);
	}
	kosaraju(V);
	
	int Q; cin >> Q;
	while (Q--) {
		int u, v;
		cin >> u >> v;
		cout << (id[u] == id[v]) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5088
final_rank: 12