// Original C++ solution (slower):
#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <algorithm>

using namespace std;

#define inf (0x3f3f3f3f)

#define ls int len=s.size()

#define ls1 int len1=s1.size()

#define sd(x) scanf("%d",&x)

#define slld(x) scanf("%I64d",&x)

#define reps(i,n) for(int i=1;i<n;i++)

#define rep(i,n) for(int i=0;i<n;i++)

#define repn(i,n) for(int i=n-1;i>=0;i--)

typedef long long int LL;

typedef long long int ll;



#include <iostream>

#include <sstream>

#include <vector>

#include <set>

#include <map>

#include <queue>

#include <string>

#include<stack>

#include<ctime>

void g(int t){if(t){g((t-1)/26);putchar(65+(t-1)%26);}}



const int M=2*1e5+100;

int f[M],f1[M],r[M],r1[M];



void init(int n){

    rep(i,n){

        f[i]=i;f1[i]=i;

        r[i]=r1[i]=0;

    }

}

int find(int x){

    return f[x]==x?x:f[x]=find(f[x]);

}

int find1(int x){

    return f1[x]==x?x:f1[x]=find1(f1[x]);

}

void unite(int x,int y){

    x=find(x);y=find(y);

    if(x==y) return;



    if(r[x]<r[y]) f[x]=y;

    else{

        f[y]=x;

        if(r[x]==r[y]) r[x]++;

    }

}

void unite1(int x,int y){

    x=find1(x);y=find1(y);

    if(x==y) return;

    if(r1[x]<r1[y]) f1[x]=y;

    else{

        f1[y]=x;

        if(r1[x]==r1[y]) r1[x]++;

    }

}



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



int main()

{

#ifdef LOCAL

    freopen("data.h", "r", stdin);

    //freopen("1.h","w",stdout);

#endif

    int n,K,L;

    scanf("%d%d%d",&n,&K,&L);

    init(n);

    rep(i,K){

        int v,u;

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

        unite(v,u);

    }

    rep(i,L){

        int v,u;

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

        unite1(v,u);

    }

    mp.clear();

    for(int i=1;i<=n;i++){

        mp[make_pair(find(i),find1(i))]++;

    }



    for(int i=1;i<=n;i++){

        printf("%d ",mp[make_pair(find(i),find1(i))]);

    }

    cout<<endl;

}


// Optimized solution to the same problem (faster):
#include<cstdio>

#include<cstring>

#include<algorithm>

struct abc {

	int aa, bb, cc;

	bool operator < (const abc&T) const {

		return(aa < T.aa || (aa == T.aa && bb < T.bb) || (aa == T.aa && bb == T.bb && cc < T.cc));

	}

	bool operator == (const abc&T) const {

		return(aa == T.aa && bb == T.bb);

	}

} ans[200005];

using namespace std;

int N, KK, LL, i, j, k, l, m, n, pt1[200005], pt2[200005], s1[200005], s2[200005], z;

int sz[200005], ans2[200005];

int find1(int aa) {

	if(pt1[aa] != aa) 

		pt1[aa] = find1(pt1[aa]);

	return(pt1[aa]);

}

int find2(int bb) {

	if(pt2[bb] != bb) 

		pt2[bb] = find2(pt2[bb]);

	return(pt2[bb]);

}

int main() {

	scanf("%d%d%d", &N, &KK, &LL);

	for(i = 1; i <= N; i++) {

		pt1[i] = i;

		pt2[i] = i;

		s1[i] = 1;

		s2[i] = 1;

	}

	for(i = 0; i < KK; i++) {

		scanf("%d%d", &j, &l);

		if(find1(j) == find1(l)) continue;

		s1[find1(l)] += s1[find1(j)];

		pt1[find1(j)] = find1(l);

	}

	

	for(i = 0; i < LL; i++) {

		scanf("%d%d", &j, &l);

		if(find2(j) == find2(l)) continue;

		s2[find2(l)] += s2[find2(j)];

		pt2[find2(j)] = find2(l);

	}

	for(i = 1; i <= N; i++) {

		pt1[i] = find1(i);

		pt2[i] = find2(i);

		ans[i].aa = pt1[i];

		ans[i].bb = pt2[i];

		ans[i].cc = i;

	}

//	for(i = 1; i <= N; i++) printf("%d %d\n", pt1[i], pt2[i]);

	

	sort(ans + 1, ans + N + 1);

	sz[1] = 1;

	for(i = 2; i <= N; i++) if(ans[i] == ans[i - 1]) {

		sz[i] = sz[i - 1] + 1;

	} else {

		sz[i] = 1;

	}

	for(i = N - 1; i >= 1; i--) 

	if(ans[i] == ans[i + 1]) sz[i] = sz[i + 1];

	

	//for(i = 1; i <= N; i++) printf("%d %d %d %d\n", ans[i].aa, ans[i].bb, ans[i].cc, sz[i]);

	

	for(i = 1; i <= N; i++) ans2[ans[i].cc] = sz[i];

	

	for(i = 1; i < N; i++) printf("%d ", ans2[i]);

	printf("%d\n", ans2[N]);

}

// Fastest known solution for this problem: