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

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Main {

	private static List<Integer>[] G;
	private static List<Integer>[] rG;
	private static ArrayList<Integer> vs = new ArrayList<Integer>();
	private static boolean[] used;
	private static int[] cmp;

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		int V = nextInt();
		int E = nextInt();

		G = new List[V];
		rG = new List[V];
		for (int i = 0; i < V; i++) {
			G[i] = new ArrayList<Integer>();
			rG[i] = new ArrayList<Integer>();
		}

		for (int i = 0; i < E; i++) {
			int from = nextInt();
			int to = nextInt();
			G[from].add(to);
			rG[to].add(from);
		}

		used = new boolean[V];
		cmp = new int[V];
		for (int i = 0; i < V; i++) {
			if (!used[i]) {
				dfs(i);
			}
		}

		used = new boolean[V];
		int k = 0;
		for (int i = vs.size() - 1; i >= 0; i--) {
			if (!used[vs.get(i)]) {
				rdfs(vs.get(i), k++);
			}
		}

		List<Integer>[] groups = new List[k];
		for (int i = 0; i < groups.length; i++) {
			groups[i] = new ArrayList<Integer>();
		}
		for (int i = 0; i < cmp.length; i++) {
			groups[cmp[i]].add(i);
		}

		int Q = nextInt();
		for (int i = 0; i < Q; i++) {
			int u = nextInt();
			int v = nextInt();
			if (cmp[u] == cmp[v]) {
				System.out.println(1);
			} else {
				System.out.println(0);
			}
		}

	}

	static void dfs(int v) {
		used[v] = true;
		for (int i = 0; i < G[v].size(); i++) {
			if (!used[G[v].get(i)]) {
				dfs(G[v].get(i));
			}
		}
		vs.add(v);
	}

	static void rdfs(int v, int k) {
		used[v] = true;
		cmp[v] = k;
		for (int i = 0; i < rG[v].size(); i++) {
			if (!used[rG[v].get(i)]) {
				rdfs(rG[v].get(i), k);
			}
		}
	}

	static int nextInt() {
		int c;
		try {
			c = System.in.read();
			while (c != '-' && (c < '0' || c > '9'))
				c = System.in.read();
			if (c == '-')
				return -nextInt();
			int res = 0;
			while (c >= '0' && c <= '9') {
				res = res * 10 + c - '0';
				c = System.in.read();
			}
			return res;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
	}

}