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

#include <cstdio>

#include <vector>

#include <map>

#include <algorithm>

#include <cstring>



using namespace std;

typedef long long LL;

const int maxn = 4e5 + 8;



///有时可能需要 并查集+离散化



///并查集可以直接写成1个类，然后2个并查集建2个对象就可以，这里就直接朴素写法的并查集了 Y ^_^ Y

int father[maxn], _rank[maxn];

void DisjointSet(int n)

{

    for(int i = 0; i <= n; i++)

    {

        father[i] = i;

        _rank[i] = 0;

    }

}



int _find(int v)

{

    return father[v] = father[v] == v ? v : _find(father[v]);

    ///同时压缩路径，有时不能压缩路径，有时必须压缩路径，看具体情况

}



void _merge(int x, int y)

{

    int a = _find(x), b = _find(y);                //

    if(_rank[a] < _rank[b])

    {

        father[a] = b;

    }

    else

    {

        father[b] = a;

        if(_rank[a] == _rank[b])

        {

            _rank[a]++;

        }

    }

}





int father1[maxn], _rank1[maxn];

void DisjointSet1(int n)

{

    for(int i = 0; i <= n; i++)

    {

        father1[i] = i;

        _rank1[i] = 0;

    }

}



int _find1(int v)

{

    return father1[v] = father1[v] == v ? v : _find1(father1[v]);

    ///同时压缩路径，有时不能压缩路径，有时必须压缩路径，看具体情况

}



void _merge1(int x, int y)

{

    int a = _find1(x), b = _find1(y);                //

    if(_rank1[a] < _rank1[b])

    {

        father1[a] = b;

    }

    else

    {

        father1[b] = a;

        if(_rank1[a] == _rank1[b])

        {

            _rank1[a]++;

        }

    }

}





map<int, vector<int> > mp1, mp2;

map<int, int> cnt;

int ans[maxn];



int main()

{

    int n, p, q, u, v;

    cin >> n >> p >> q;

    DisjointSet(n), DisjointSet1(n);

    while(p--)

    {

        cin >> u >> v;

        if(_find(u) != _find(v)) _merge(_find(u), _find(v));

    }



    while(q--)

    {

        cin >> u >> v;

        if(_find1(u) != _find1(v)) _merge1(_find1(u), _find1(v));

    }



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

    {

        mp1[_find(i)].push_back(i);

    }

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

    {

        mp2[_find1(i)].push_back(i);

    }



    for(map <int, vector<int> > :: iterator i = mp1.begin(); i != mp1.end(); i++)

    {

        sort((i->second).begin(), (i->second).end());

    }

    for(map <int, vector<int> > :: iterator i = mp2.begin(); i != mp2.end(); i++)

    {

        sort((i->second).begin(), (i->second).end());

    }



    //cout << "?"<<endl;



    int i, a, b, pa, pb, sza, szb, l, r, mid;

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

    {

        if(ans[i] != 0) continue;

        pa = _find(i);

        pb = _find1(i);

        sza = mp1[pa].size(), szb = mp2[pb].size();

        cnt.clear();

        a = 0, b = 0;

        while(a < sza && b < szb)

        {

            if(mp1[pa][a] == mp2[pb][b])

            {

                cnt[mp1[_find(i)][a]]++;

                a++;

                b++;

            }

            else if(mp1[pa][a] > mp2[pb][b])

            {

                if(b + 1== szb)

                {

                    break;

                }

                else if(mp1[pa][a] > mp2[pb][szb - 1])

                {

                    break;

                }

                else

                {

                    l = b, r = szb;

                    b = szb - 1;

                    while(l + 1 < r)

                    {

                        mid = (l + r) >> 1;

                        if(mp1[pa][a] <= mp2[pb][mid])

                        {

                            r = mid;

                            b = min(b, mid);

                        }

                        else l = mid;

                    }



                }

            }

            else

            {

                if(a + 1 == sza)

                {

                    break;

                }

                else if(mp1[pa][sza - 1] < mp2[pb][b])

                {

                    break;

                }

                else

                {

                    l = a, r = sza;

                    a = sza - 1;

                    while(l + 1 < r)

                    {

                        mid = (l + r) >> 1;

                        if(mp1[pa][mid] >= mp2[pb][b])

                        {

                            r = mid;

                            a = min(a, mid);

                        }

                        else l = mid;

                    }

                }

            }

        }

        sza = cnt.size();

        for(map <int, int> :: iterator k = cnt.begin(); k != cnt.end(); k++)

        {

            ans[k->first] = sza;

        }

    }



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

    {

        if(i == 1) cout << ans[i];

        else cout << " " << ans[i];

    }

    cout << endl;

    return 0;

}


// Optimized solution to the same problem (faster):
/*Lucky_Glass*/

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>

#include<map>

using namespace std;

const int MAXN=int(2e5);

int n,p,q;

int fa[2][MAXN+5];

map< pair<int,int> ,int> cnt;

int Find(int x,int y)

{

	if(fa[y][x]==x) return x;

	return fa[y][x]=Find(fa[y][x],y);

}

int main()

{

	scanf("%d%d%d",&n,&p,&q);

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

		fa[0][i]=fa[1][i]=i;

	for(int i=0,u,v;i<p;i++)

	{

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

		if(Find(u,0)!=Find(v,0))

			fa[0][fa[0][u]]=fa[0][v];

	}

	for(int i=0,u,v;i<q;i++)

	{

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

		if(Find(u,1)!=Find(v,1))

			fa[1][fa[1][u]]=fa[1][v];

	}

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

		cnt[make_pair(Find(i,0),Find(i,1))]++;

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

	{

		if(i!=1) printf(" ");

		printf("%d",cnt[make_pair(fa[0][i],fa[1][i])]);

	}

	printf("\n");

	return 0;

}


// Fastest known solution for this problem: