Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Connected Components

Write a program which reads relations in a SNS (Social Network Service), and judges that given pairs of users are reachable each other through the network.

Input

In the first line, two integer $n$ and $m$ are given. $n$ is the number of users in the SNS and $m$ is the number of relations in the SNS. The users in the SNS are identified by IDs $0, 1, ..., n-1$.

In the following $m$ lines, the relations are given. Each relation is given by two integers $s$ and $t$ that represents $s$ and $t$ are friends (and reachable each other).

In the next line, the number of queries $q$ is given. In the following $q$ lines, $q$ queries are given respectively. Each query consists of two integers $s$ and $t$ separated by a space character.

Output

For each query, print "yes" if $t$ is reachable from $s$ through the social network, "no" otherwise.

Constraints

$2 \leq n \leq 100,000$

$0 \leq m \leq 100,000$

$1 \leq q \leq 10,000$

Sample Input

10 9
0 1
0 2
3 4
5 7
5 6
6 7
6 8
7 8
8 9
3
0 1
5 9
1 3

Sample Output

yes
yes
no

Solution in JAVA (judge verdict: Accepted)

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

public class Main {
	static DisjointSet set;
	
	public static void buildSet(Graph g) {
		set = new DisjointSet(g);
	}
	public static boolean connected(int first, int second){
		return set.find(first) == set.find(second);
	}
	

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int users = scan.nextInt();
		int relations = scan.nextInt();
		
		Graph g = new Graph();
		int id, connection;
		for(int i = 0; i < relations; i++) {
			id = scan.nextInt();
			connection = scan.nextInt();
			g.addConnection(new Vertex(id, new int[] {connection}));
		}
		
		buildSet(g);
		
		int queries = scan.nextInt();
		for(int i = 0; i < queries; i++) {
			id = scan.nextInt();
			connection = scan.nextInt();
			System.out.println(connected(id, connection) ? "yes" : "no");
		}
		scan.close();
	}
}

class DisjointSet{
	int[] parent;
	
	public DisjointSet(Graph g) {
		HashMap<Integer, ArrayList<Integer>> graph = g.getGraph();
		ArrayList<Integer> ids = new ArrayList<Integer>(graph.keySet());
		int max = getMax(ids);
		
		if(max > 0)
			parent = new int[max + 1];
		else
			parent = new int[0];

		for(int i = 0; i < parent.length; i++)
			parent[i] = i;
		
		for(Integer id: ids) {
			for(Integer neighbor: graph.get(id))
				union(neighbor, id);
		}
		// displayParent(); // for debugging
	}
	
	public void union(int x, int y) {
		int r1 = find(x);
		int r2 = find(y);
		if(r1 != r2)
			parent[r1] = r2;
	}
	
	public int find(int x) {
		if(parent.length == 0)
			return x;
		if(parent.length <= x)
			return x;
		
		int current = x;
		if(parent[current] == current)
			return current;
		parent[current] = find(parent[current]);
		return parent[current];
	}
	
	public int getMax(ArrayList<Integer> nums) {
		int max = Integer.MIN_VALUE;
		for(int i = 0; i < nums.size(); i++) {
			if(nums.get(i) > max)
				max = nums.get(i);
		}
		
		return max;
	}
	
	public void displayParent() {
		System.out.println();
		String indexStr = "{";
		String arrStr = "{";
		for(int i = 0; i < parent.length; i++) {
			indexStr += i + ", ";
			arrStr += parent[i] + ", ";
		}
		indexStr = indexStr.substring(0, indexStr.length() - 2) + "}";
		arrStr = arrStr.substring(0, arrStr.length() - 2) + "}";
		
		System.out.println(indexStr);
		System.out.println(arrStr);
	}
}

class Graph{
	private HashMap<Integer, ArrayList<Integer>> graph;
	
	public Graph(ArrayList<Vertex> vertices) {
		graph = new HashMap<Integer, ArrayList<Integer>>();
		for(Vertex v: vertices)
			addConnection(v);
	}
	public Graph(Vertex[] vertices) {
		graph = new HashMap<Integer, ArrayList<Integer>>();
		for(int i = 0; i < vertices.length; i++)
			addConnection(vertices[i]);
	}
	public Graph() {
		graph = new HashMap<Integer, ArrayList<Integer>>();
	}
	
	public void addConnection(Vertex v) {
		ArrayList<Integer> connections = graph.containsKey(v.getID()) ? graph.get(v.getID()) : new ArrayList<Integer>();
		ArrayList<Integer> neighbors = v.getConnections();
		for(Integer neighbor: neighbors) {
			if(!connections.contains(neighbor))
				connections.add(neighbor);
		}
		
		Collections.sort(connections);
		graph.put(v.getID(), connections);
		
		ArrayList<Integer> neighborConnections;
		for(Integer neighbor: neighbors) {
			neighborConnections = graph.containsKey(neighbor) ? graph.get(neighbor) : new ArrayList<Integer>();
			if(!neighborConnections.contains(v.getID()))
				addConnection(new Vertex(neighbor, new int[] {v.getID()}));
		}
	}
	
	public HashMap<Integer, ArrayList<Integer>> getGraph() {
		return graph;
	}
	public int getNumVertices() {
		return graph.size();
	}
	public String toString() {
		return graph.toString();
	}
}

class Vertex{
	private int id;
	private ArrayList<Integer> connections;
	
	public Vertex(int id, ArrayList<Integer> connections) {
		this.id = id;
		this.connections = connections;
	}
	public Vertex(int id, int[] cons) {
		this.id = id;
		connections = new ArrayList<Integer>();
		for(int i = 0; i < cons.length; i++)
			connections.add(cons[i]);
	}
	
	public void addConnection(int n) {
		if(!connections.contains(n))
			connections.add(n);
		Collections.sort(connections);
		
	}
	
	public int getID() {
		return id;
	}
	public ArrayList<Integer> getConnections() {
		return connections;
	}
	
	public String toString() {
		return id + " -> " + connections;
	}
}