### BUGGY CODE ###

def find_train(x): # 木の根を求める
    if par_train[x]==x:
        return x
    else:
        return find_train(par_train[x])

def unite_train(x,y): # xとyの属する集合を併合
    x=find_train(x)
    y=find_train(y)
    if x==y:return
    if rank_train[x]<rank_train[y]:
        par_train[x]=y
    else:
        par_train[y]=x
        if rank_train[x]==rank_train[y]:
            rank_train[x]+=1

def same_train(x,y): # xとyが同じ集合に属するか判定
    return find_train(x)==find_train(y)

def find_road(x): # 木の根を求める
    if par_road[x]==x:
        return x
    else:
        return find_road(par_road[x])

def unite_road(x,y): # xとyの属する集合を併合
    x=find_road(x)
    y=find_road(y)
    if x==y:return
    if rank_road[x]<rank_road[y]:
        par_road[x]=y
    else:
        par_road[y]=x
        if rank_road[x]==rank_road[y]:
            rank_road[x]+=1

def same_road(x,y): # xとyが同じ集合に属するか判定
    return find_road(x)==find_road(y)

def main():
    # x,y = map(int,input().split())           x=1,y=2
    # a = input().split()                      a=['1','2','3',...,'n']
    # a = list(map(int,input().split()))       a=[1,2,3,4,5,...,n]
    # li = input().split('T')	              FFFTFTTFF => li=['FFF', 'F', '', 'FF']
    # 複数行の「1 2 3 4」型の入力を一配列に
    # x = sorted([list(map(int, input().split())) for _ in range(n)])
    # ソート x.sort(key=lambda y:y[1])
    # [chr(i) for i in range(97, 97+26)] 英語小文字リスト
    # [chr(i) for i in range(65, 65+26)] 英語大文字リスト atcoder
    # ord(c) chr(2) alphabet <=> number
    n,k,l = map(int,input().split()) 

    global par_train,rank_train,par_road,rank_road
    par_train=[i for i in range(n)]  # 親
    rank_train=[0 for _ in range(n)] # 木の深さ
    par_road=[i for i in range(n)]  # 親
    rank_road=[0 for _ in range(n)] # 木の深さ
    for _ in range(k):
        p,q = map(int,input().split())
        p-=1
        q-=1
        unite_train(p,q)
    for _ in range(l):
        p,q = map(int,input().split())
        p-=1
        q-=1
        unite_road(p,q)
    ans=[0 for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if same_road(i,j):
                if same_train(i,j):
                    ans[i]+=1
    for i in range(n):
        print(ans[i])

main()

### FIXED CODE ###

from collections import Counter,defaultdict,deque
import sys,bisect,math,itertools,string,queue,copy
from heapq import heappop, heappush
input = sys.stdin.readline
sys.setrecursionlimit(10**8)
mod = 10**9+7

def inp(): # n=1
    return int(input())
def inpm(): # x=1,y=2
    return map(int,input().split())
def inpl(): # a=[1,2,3,4,5,...,n]
    return list(map(int, input().split()))
def inpls(): # a=['1','2','3',...,'n']
    return list(input().split())
def inpln(n): # x=[] 複数行
    return list(int(input()) for _ in range(n))
def inpll(n): # [[1,1,1,1],[2,2,2,2],[3,3,3,3]]
    return sorted([list(map(int, input().split())) for _ in range(n)])
def sortx(x,n,k):
    if k == 0:x.sort(key=lambda y:y[1,n])
    else:x.sort(reversed=True, key=lambda y:y[1,n])

def find(x): # 木の根を求める
    if par[x]==x:
        return x
    else:
        return find(par[x])

def unite(x,y): # xとyの属する集合を併合
    x=find(x)
    y=find(y)
    if x==y:return
    if rank[x]<rank[y]:
        par[x]=y
    else:
        par[y]=x
        if rank[x]==rank[y]:
            rank[x]+=1

def same(x,y): # xとyが同じ集合に属するか判定
    return find(x)==find(y)
 
def main():
    n,k,l = inpm()
 
    global par,rank
    par  = [i for i in range(2*n)]
    rank = [-1 for _ in range(2*n)] 
    for _ in range(k):
        p,q = inpm()
        p-=1
        q-=1
        unite(p,q)
    for _ in range(l):
        r,s = inpm()
        r-=1
        s-=1
        unite(r+n,s+n)

    root_s=defaultdict(int)
    root=[]
    for i in range(n):
        root.append(str(find(i))+' '+str(find(i+n)))
        root_s[root[i]]+=1
    
    ans=[0 for _ in range(n)]
    for i in range(n):
        ans[i] = root_s[root[i]]
    print(*ans) 


if __name__ == "__main__":
    main()