// Slower C++ solution:
#include <iostream>

#include <string.h>

#include <stdio.h>

#include <queue>

#include <vector>

#include <map>

#include <algorithm>

using namespace std;

const int Max=3e5+100;

int get_root(int *f, int root){

    return f[root]==root?root:f[root]=get_root(f, f[root]);

}

void merge(int *f, int x,int y){

    int i=get_root(f, x);

    int j=get_root(f, y);

    f[i]=j;

}

int f[Max], g[Max];

void init(int n){

    for(int a=0; a<=n; a++)f[a]=a, g[a]=a;

}

int vis[Max], num[Max];

vector<int> vec[Max];

map<int, int>ma;

int main(){

    int n, m, k, u, v;

    scanf("%d%d%d", &n, &m, &k);

    init(n);

    for(int a=0; a<m; a++){

        scanf("%d%d", &u, &v);

        merge(f, u, v);

    }

    for(int a=0; a<k; a++){

        scanf("%d%d", &u, &v);

        merge(g, u, v);

    }

    for(int a=1; a<=n; a++)vec[get_root(f, a)].push_back(a);

    for(int a=0; a<=n; a++){

        ma.clear();

       // memset(num, 0, sizeof(num));

        for(int b=0; b<vec[a].size(); b++){

            ma[get_root(g, vec[a][b])]++;

            //num[get_root(g, vec[a][b])]++;

        }

        for(int b=0; b<vec[a].size(); b++){

            vis[vec[a][b]]+=ma[get_root(g, vec[a][b])];

        }

    }

    for(int a=1; a<=n; a++)printf("%d%c", vis[a], a==n?'\n':' ');

    return  0;

}

// Faster C++ solution for the same problem (measured speedup: 9.167664152576503x):
/*

7 4 4

1 2

2 3

2 5

6 7

3 5

4 5

3 4

6 7

*/

#include <bits/stdc++.h>

using namespace std; using ll = long long; using ld = long double; using pii = pair<int, int>; const int N = 5e5 + 5, M = 998244353, INF = 0x3f3f3f3f; const ll LNF = 0x3f3f3f3f3f3f3f3f; void Main();

void debug() { cerr << endl; } template <typename T, typename... Ts> void debug(T x, Ts... y) { cerr << "\033[31m" << x << "\033[0m"; if (sizeof...(y) > 0) cerr << ' '; debug(y...); } template <typename T> void debug(const T& a, int l, int r, char c) { for (int i = l; i <= r; ++i) cerr << "\033[31m" << a[i] << "\033[0m" << (i == r ? '\n' : c); }

void print() { cout << '\n'; } template <typename T, typename... Ts> void print(T x, Ts... y) { cout << x; if (sizeof...(y) > 0) cout << ' '; print(y...); } template <typename T> void print(const T& a, int l, int r, char c) { for (int i = l; i <= r; ++i) cout << a[i] << (i == r ? '\n' : c); }

void input() {} template <typename T, typename... Ts> void input(T& x, Ts&... y) { cin >> x; input(y...); } template <typename T> void input(T* a, int l, int r) { for (int i = l; i <= r; ++i) cin >> a[i]; } template <typename T> void input(vector<T>& a, int l, int r) { for (int i = l; i <= r; ++i) cin >> a[i]; }

template <typename T> void Max(T& a, T b) { if (a < b) a = b; } template <typename T> void Min(T& a, T b) { if (a > b) a = b; } template <typename T> void Add(T& a, T b) { a += b; if (a > M) a -= M; if (a < 0) a += M; } template <typename T> void Mul(T& a, T b) { a = a * b % M; } template <typename T> T Mod(T a) { return (a % M + M) % M; }

int main(int argc, char** argv) {

    ios::sync_with_stdio(0); cin.tie(0); /* cout << setprecision(10) << fixed; */

#ifdef Zmm

    if (argc) { freopen((string(*(argv)).substr(2, string(*(argv)).size() - 6) + string(".cpp")).c_str(), "r", stdin); string x; cin >> x; }

#endif

    Main();

}

struct DSU {

    int p[N];

    void init(int n) { iota(p + 1, p + n + 1, 1); }

    int find(int x) { return p[x] == x ? x : (p[x] = find(p[x])); }

    void unite(int u, int v) { p[find(u)] = find(v); }

} a, b;

void Main() {

    int n, K, L;

    input(n, K, L);

    a.init(n);

    b.init(n);

    for (int i = 0; i < K; ++i) {

        int u, v;

        input(u, v);

        a.unite(u, v);

    }

    for (int i = 0; i < L; ++i) {

        int u, v;

        input(u, v);

        b.unite(u, v);

    }

    map<pair<int, int>, int> mp;

    for (int i = 1; i <= n; ++i) ++mp[{a.find(i), b.find(i)}];

    for (int i = 1; i <= n; ++i) cout << mp[{a.p[i], b.p[i]}] << " \n"[i == n];

}