Problem:
Score : 400 points

Problem Statement

There are N cities. There are also K roads and L railways, extending between the cities.
The i-th road bidirectionally connects the p_i-th and q_i-th cities, and the i-th railway bidirectionally connects the r_i-th and s_i-th cities.
No two roads connect the same pair of cities. Similarly, no two railways connect the same pair of cities.

We will say city A and B are connected by roads if city B is reachable from city A by traversing some number of roads. Here, any city is considered to be connected to itself by roads.
We will also define connectivity by railways similarly.

For each city, find the number of the cities connected to that city by both roads and railways.

Constraints

2 ≦ N ≦ 2*10^5

1 ≦ K, L≦ 10^5

1 ≦ p_i, q_i, r_i, s_i ≦ N

p_i < q_i

r_i < s_i

When i ≠ j, (p_i, q_i) ≠ (p_j, q_j)

When i ≠ j, (r_i, s_i) ≠ (r_j, s_j)

Input

The input is given from Standard Input in the following format:

N K L
p_1 q_1
:
p_K q_K
r_1 s_1
:
r_L s_L

Output

Print N integers. The i-th of them should represent the number of the cities connected to the i-th city by both roads and railways.

Sample Input 1

4 3 1
1 2
2 3
3 4
2 3

Sample Output 1

1 2 2 1

All the four cities are connected to each other by roads.

By railways, only the second and third cities are connected. Thus, the answers for the cities are 1, 2, 2 and 1, respectively.

Sample Input 2

4 2 2
1 2
2 3
1 4
2 3

Sample Output 2

1 2 2 1

Sample Input 3

7 4 4
1 2
2 3
2 5
6 7
3 5
4 5
3 4
6 7

Sample Output 3

1 1 2 1 2 2 2

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Time Limit Exceeded)




import java.util.Scanner;
import java.util.TreeMap;

/**
 * arc065 D http://arc065.contest.atcoder.jp/tasks/arc065_b
 * need to use findUnion with weight optimization
 * **TLE if you move the solution to Main, maybe it is because you need to put UnionFind as static class**
 * */
public class Main {


     class UnionFind{
//        int count =0;
        int []id;
        int []weight;
        //int []dataCnt;
        public void init(int n){
            id=new int[n];
            weight = new int[n];
          //  dataCnt = new int[n];
//            count=n;

            for(int i=0;i<n;i++){
                id[i]=i;
            //    dataCnt[i]=1;
            }

        }
//        public int getDataCnt(int n){
//            return dataCnt[id[n]];
//        }
//        public int getCount(){return count;}
       // public int find(int p){return id[p];}
        private int find(int p)
        {
            // 寻找p节点所在组的根节点，根节点具有性质id[root] = root
            while (p != id[p]) p = id[p];
            return p;
        }
        public void union(int p, int q)
        {
            // Give p and q the same root.
            int pRoot = find(p);
            int qRoot = find(q);
            if (pRoot == qRoot)
                return;
           // id[pRoot] = qRoot;    // 将一颗树(即一个组)变成另外一课树(即一个组)的子树
            if(weight[pRoot] < weight[qRoot]) id[pRoot] = qRoot;
            else{
                id[pRoot] = qRoot;
                if(weight[pRoot] == weight[qRoot]) weight[pRoot]++;
            }
//            count--;
        }
//        public boolean isConnected(int p,int q){
//            return (find(p)==find(q));
//        }
//        public void union(int p,int q){
//            int pID = find(p);
//            int qID = find(q);
//            if(pID==qID) return;
//            for(int i=0;i<id.length;i++) {
//                if (id[i] == pID) id[i] = qID;
//            }
//        }

    }

    private void solution(){
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int K = sc.nextInt();
        int L = sc.nextInt();

        UnionFind road = new UnionFind();
        road.init(N);
        UnionFind rail = new UnionFind();
        rail.init(N);

        for(int i=0;i<K;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            road.union(a-1,b-1);
        }


        for(int i=0;i<L;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            rail.union(a-1,b-1);
        }


        TreeMap<Long,Integer> map = new TreeMap<>();
        Long key = 0L;
        for(int i=0;i<N;i++){
            key = (long)road.find(i)*N+rail.find(i);
            if(map.containsKey(key)){
                map.put(key,map.get(key)+1);
            }
            else{
                map.put(key,1);
            }
        }

        StringBuilder sb = new StringBuilder();
        for(int i=0;i<N;i++){
            key =(long) road.find(i)*N+rail.find(i);
            if(i!=N-1)
                sb.append(map.get(key)+" ");
            else
                sb.append(map.get(key));
        }

        System.out.println(sb.toString());
        sc.close();
    }

    public static void main(String[] args) {
      new Main().solution();
    }

}

//class UnionFind {
//    //        int count =0;
//    int[] id;
//    int[] weight;
//
//    //int []dataCnt;
//    public void init(int n) {
//        id = new int[n];
//        weight = new int[n];
//        //  dataCnt = new int[n];
////            count=n;
//
//        for (int i = 0; i < n; i++) {
//            id[i] = i;
//            //    dataCnt[i]=1;
//        }
//
//    }
//
//    //        public int getDataCnt(int n){
////            return dataCnt[id[n]];
////        }
////        public int getCount(){return count;}
//    // public int find(int p){return id[p];}
//    public int find(int p) {
//        // 寻找p节点所在组的根节点，根节点具有性质id[root] = root
//        while (p != id[p]) p = id[p];
//        return p;
//    }
//
//    public void union(int p, int q) {
//        // Give p and q the same root.
//        int pRoot = find(p);
//        int qRoot = find(q);
//        if (pRoot == qRoot)
//            return;
//        // id[pRoot] = qRoot;    // 将一颗树(即一个组)变成另外一课树(即一个组)的子树
//        if (weight[pRoot] < weight[qRoot]) id[pRoot] = qRoot;
//        else {
//            id[pRoot] = qRoot;
//            if (weight[pRoot] == weight[qRoot]) weight[pRoot]++;
//        }
////            count--;
//    }
//}