from collections import*

import sys

input=sys.stdin.readline





class UNION_FIND(object):

    def __init__(self,n):

        #親の番号を格納する。親だった場合は-(その集合のサイズ)

        #作るときはParentの値を全て-1にする

        #こうすると全てバラバラになる

        self.parent=[-1 for i in range(n)]

        

    def root(self,x):

        #Aがどのグループに属しているか調べる

        if self.parent[x]<0:

            return x

        else:

            self.parent[x]=self.root(self.parent[x])  #親を再帰で探知 再帰は最後に上のifにひっかかる

            return self.parent[x]

 

    def size(self,x):

        #自分のいるグループの頂点数を調べる

        return -self.parent[self.root(x)]   #親をとってきたい

        

    def union(self,x,y):

        #AとBをくっ付ける

        #AとBを直接つなぐのではなく、root(A)にroot(B)をくっつける

        #print(self.parent)

        x=self.root(x)

        y=self.root(y)

        #print(x,y)

        if x==y:   #すでにくっついてるからくっ付けない

            return False

            

        #大きい方(A)に小さいほう(B)をくっ付けたい

        #大小が逆だったらひっくり返しちゃう。

        if self.size(x)<self.size(y):

            x,y=y,x

        self.parent[x]+=self.parent[y]  #Aのサイズを更新する

        self.parent[y]=x   #Bの親をAに変更する

        return True

        

n,k,l=list(map(int,input().split()))

u1=UNION_FIND(n)

u2=UNION_FIND(n)

d=defaultdict(int)

for i in range(k):

    p,q=list(map(int,input().split()))

    u1.union(p-1,q-1)

for i in range(l):

    p,q=list(map(int,input().split()))

    u2.union(p-1,q-1)

for i in range(n):

    d[(u1.root(i),u2.root(i))]+=1

print((*[d[(u1.root(i),u2.root(i))]for i in range(n)]))
from collections import*

import sys

input = sys.stdin.readline





class UnionFind(object):

    def __init__(self, n):

        # 親の番号を格納する。親だった場合は-(その集合のサイズ)

        # 作るときはParentsの値を全て-1にする

        # こうすると全てバラバラになる

        self.parents = [-1 for i in range(n)]



    def find(self, x):

        if self.parents[x] < 0:

            return x

        else:

            self.parents[x] = self.find(self.parents[x])

            return self.parents[x]



    def union(self, x, y):

        x = self.find(x)

        y = self.find(y)



        if x == y:

            return



        if self.parents[x] > self.parents[y]:

            x, y = y, x



        self.parents[x] += self.parents[y]

        self.parents[y] = x

        return



    def size(self, x):

        return -self.parents[self.find(x)]





n, k, l = list(map(int, input().split()))

ro_cl = UnionFind(n)

ra_cl = UnionFind(n)

d = defaultdict(int)

for i in range(k):

    p, q = list(map(int, input().split()))

    ro_cl.union(p-1, q-1)

for i in range(l):

    p, q = list(map(int, input().split()))

    ra_cl.union(p-1, q-1)

for i in range(n):

    d[(ro_cl.find(i), ra_cl.find(i))] += 1

print((*[d[(ro_cl.find(i), ra_cl.find(i))]for i in range(n)]))
from collections import *
import sys

input = sys.stdin.readline


class UNION_FIND(object):
    def __init__(self, n):
        # 親の番号を格納する。親だった場合は-(その集合のサイズ)
        # 作るときはParentの値を全て-1にする
        # こうすると全てバラバラになる
        self.parent = [-1 for i in range(n)]

    def root(self, x):
        # Aがどのグループに属しているか調べる
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.root(self.parent[x])  # 親を再帰で探知 再帰は最後に上のifにひっかかる
            return self.parent[x]

    def size(self, x):
        # 自分のいるグループの頂点数を調べる
        return -self.parent[self.root(x)]  # 親をとってきたい

    def union(self, x, y):
        # AとBをくっ付ける
        # AとBを直接つなぐのではなく、root(A)にroot(B)をくっつける
        # print(self.parent)
        x = self.root(x)
        y = self.root(y)
        # print(x,y)
        if x == y:  # すでにくっついてるからくっ付けない
            return False
        # 大きい方(A)に小さいほう(B)をくっ付けたい
        # 大小が逆だったらひっくり返しちゃう。
        if self.size(x) < self.size(y):
            x, y = y, x
        self.parent[x] += self.parent[y]  # Aのサイズを更新する
        self.parent[y] = x  # Bの親をAに変更する
        return True


n, k, l = list(map(int, input().split()))
u1 = UNION_FIND(n)
u2 = UNION_FIND(n)
d = defaultdict(int)
for i in range(k):
    p, q = list(map(int, input().split()))
    u1.union(p - 1, q - 1)
for i in range(l):
    p, q = list(map(int, input().split()))
    u2.union(p - 1, q - 1)
for i in range(n):
    d[(u1.root(i), u2.root(i))] += 1
print((*[d[(u1.root(i), u2.root(i))] for i in range(n)]))

from collections import *
import sys

input = sys.stdin.readline


class UnionFind(object):
    def __init__(self, n):
        # 親の番号を格納する。親だった場合は-(その集合のサイズ)
        # 作るときはParentsの値を全て-1にする
        # こうすると全てバラバラになる
        self.parents = [-1 for i in range(n)]

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x
        return

    def size(self, x):
        return -self.parents[self.find(x)]


n, k, l = list(map(int, input().split()))
ro_cl = UnionFind(n)
ra_cl = UnionFind(n)
d = defaultdict(int)
for i in range(k):
    p, q = list(map(int, input().split()))
    ro_cl.union(p - 1, q - 1)
for i in range(l):
    p, q = list(map(int, input().split()))
    ra_cl.union(p - 1, q - 1)
for i in range(n):
    d[(ro_cl.find(i), ra_cl.find(i))] += 1
print((*[d[(ro_cl.find(i), ra_cl.find(i))] for i in range(n)]))

-class UNION_FIND(object): +class UnionFind(object): -        # 作るときはParentの値を全て-1にする +        # 作るときはParentsの値を全て-1にする -        self.parent = [-1 for i in range(n)] +        self.parents = [-1 for i in range(n)] -    def root(self, x): -        # Aがどのグループに属しているか調べる -        if self.parent[x] < 0: +    def find(self, x): +        if self.parents[x] < 0: -            self.parent[x] = self.root(self.parent[x])  # 親を再帰で探知 再帰は最後に上のifにひっかかる -            return self.parent[x] +            self.parents[x] = self.find(self.parents[x]) +            return self.parents[x] + +    def union(self, x, y): +        x = self.find(x) +        y = self.find(y) +        if x == y: +            return +        if self.parents[x] > self.parents[y]: +            x, y = y, x +        self.parents[x] += self.parents[y] +        self.parents[y] = x +        return -        # 自分のいるグループの頂点数を調べる -        return -self.parent[self.root(x)]  # 親をとってきたい - -    def union(self, x, y): -        # AとBをくっ付ける -        # AとBを直接つなぐのではなく、root(A)にroot(B)をくっつける -        # print(self.parent) -        x = self.root(x) -        y = self.root(y) -        # print(x,y) -        if x == y:  # すでにくっついてるからくっ付けない -            return False -        # 大きい方(A)に小さいほう(B)をくっ付けたい -        # 大小が逆だったらひっくり返しちゃう。 -        if self.size(x) < self.size(y): -            x, y = y, x -        self.parent[x] += self.parent[y]  # Aのサイズを更新する -        self.parent[y] = x  # Bの親をAに変更する -        return True +        return -self.parents[self.find(x)] -u1 = UNION_FIND(n) -u2 = UNION_FIND(n) +ro_cl = UnionFind(n) +ra_cl = UnionFind(n) -    u1.union(p - 1, q - 1) +    ro_cl.union(p - 1, q - 1) -    u2.union(p - 1, q - 1) +    ra_cl.union(p - 1, q - 1) -    d[(u1.root(i), u2.root(i))] += 1 -print((*[d[(u1.root(i), u2.root(i))] for i in range(n)])) +    d[(ro_cl.find(i), ra_cl.find(i))] += 1 +print((*[d[(ro_cl.find(i), ra_cl.find(i))] for i in range(n)]))