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 C (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <stdio.h>
#include <stdlib.h>


//解説
//普通は merge() と getGroup() だけで良い
//今回は、道路と鉄道で共に連結の時に限って同じグループとしなければならない
//group1はSides1（道路）について、連結か否かのグループ
//group2はSides1とSides2両方を考慮した時に、同じグループか否か
//つまり、group2が真のグループ配列
void merge(int posA, int posB, int *group1);
void merge2(int posA, int posB, int *group1, int *group2);
int getGroup(int pos, int *group);

//各グループの代表値のみ、変える。
//代表値とは、pos==group[pos]が成立するposのこと
//引数の時点で、groupAとgroupBはpos
void merge(int posA, int posB, int *group1){
  int groupA=getGroup(posA, group1);
  int groupB=getGroup(posB, group1);
  group1[groupB]=groupA;
}

void merge2(int posA, int posB, int *group1, int *group2){
  if(getGroup(posA, group1)==getGroup(posB, group1)){
    int groupA=getGroup(posA, group2);
    int groupB=getGroup(posB, group2);
    group2[groupB]=groupA;
  }
  else{
    ;
  }
}

//posが所属するグループの代表値をとってくる。
int getGroup(int pos, int *group){
  if(pos==group[pos]){
    return group[pos];
  }
  else{
    //折角なので書き換えておく。
    group[pos]=getGroup(group[pos], group);
    return group[pos];
  }
}


int main(){
  char buf[1024];
  int N,M1,M2;

  fgets(buf,sizeof(buf),stdin);
  sscanf(buf,"%d %d %d", &N, &M1, &M2);

  int i,j;

  int **Sides1=(int **)malloc(sizeof(int *)*M1);
  for(i=0; i<M1; i++){
    Sides1[i]=(int *)malloc(sizeof(int)*2);
  }

  int **Sides2=(int **)malloc(sizeof(int *)*M2);
  for(i=0; i<M2; i++){
    Sides2[i]=(int *)malloc(sizeof(int)*2);
  }

  i=0;
  while(1){
    fgets(buf,sizeof(buf),stdin);
    sscanf(buf,"%d %d", &Sides1[i][0], &Sides1[i][1]);
    i++;
    if(i==M1){
      break;
    }
  }
  for(i=0; i<M1; i++){
    Sides1[i][0]--;
    Sides1[i][1]--;
  }

  i=0;
  while(1){
    fgets(buf,sizeof(buf),stdin);
    sscanf(buf,"%d %d", &Sides2[i][0], &Sides2[i][1]);
    i++;
    if(i==M2){
      break;
    }
  }
  for(i=0; i<M2; i++){
    Sides2[i][0]--;
    Sides2[i][1]--;
  }


  // for(i=0; i<M1; i++){
  //   printf("Sides1[%d][0] = %d, Sides1[%d][1] = %d\n", i, Sides1[i][0], i, Sides1[i][1]);
  // }
  // for(i=0; i<M2; i++){
  //   printf("Sides2[%d][0] = %d, Sides2[%d][1] = %d\n", i, Sides2[i][0], i, Sides2[i][1]);
  // }


  int *group1=(int *)malloc(sizeof(int)*N);
  int *group2=(int *)malloc(sizeof(int)*N);

  for(int k=0; k<N; k++){
    group1[k]=k;
    group2[k]=k;
  }

  for(i=0; i<M1; i++){
    merge(Sides1[i][0], Sides1[i][1], group1);
  }

  for(i=0; i<M2; i++){
    merge2(Sides2[i][0], Sides2[i][1], group1, group2);
  }

  // for(int k=0; k<N; k++){
  //   printf("group2[%d] = %d\n", k, group2[k]);
  // }

  //今回は、group[i]が等しい=同じグループというわけではないので、
  //同じグループに属する要素数を求めるアルゴリズムも書き換える必要がある。

  //count[i]は i番目の点と連結な点の数。
  int *count=(int *)calloc(N, sizeof(int));
  //代表点とは pos==group[pos] となるノード
  //その代表点のみ、count[pos]をインクリメント
  for(int i=0; i<N; i++){
    count[getGroup(i,group2)]++;
  }

  for(int i=0; i<N; i++){
      printf("%d ", count[getGroup(i,group2)]);
  }
  printf("\n");

  return 0;
}