There are N cities. There are also K roads and L railways, extending between the cities.
The i-th road bidirectionally connects the p_i-th and q_i-th cities, and the i-th railway bidirectionally connects the r_i-th and s_i-th cities.
No two roads connect the same pair of cities. Similarly, no two railways connect the same pair of cities.
We will say city A and B are connected by roads if city B is reachable from city A by traversing some number of roads. Here, any city is considered to be connected to itself by roads.
We will also define connectivity by railways similarly.
For each city, find the number of the cities connected to that city by both roads and railways.

-----Constraints-----
 - 2 ≦ N ≦ 2*10^5
 - 1 ≦ K, L≦ 10^5
 - 1 ≦ p_i, q_i, r_i, s_i ≦ N
 - p_i < q_i
 - r_i < s_i
 - When i ≠ j, (p_i, q_i) ≠ (p_j, q_j)
 - When i ≠ j, (r_i, s_i) ≠ (r_j, s_j)

-----Input-----
The input is given from Standard Input in the following format:
N K L
p_1 q_1
:
p_K q_K
r_1 s_1
:
r_L s_L

-----Output-----
Print N integers. The i-th of them should represent the number of the cities connected to the i-th city by both roads and railways.

-----Sample Input-----
4 3 1
1 2
2 3
3 4
2 3

-----Sample Output-----
1 2 2 1

All the four cities are connected to each other by roads.
By railways, only the second and third cities are connected. Thus, the answers for the cities are 1, 2, 2 and 1, respectively.

Difficulty: interview

Starter code:

Solutions:
from collections import Counter

class Unionfind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * (n+1)
        
    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
    
    def size(self, x):
        return -self.parents[self.find(x)]
    
    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
    
    def group_count(self):
        return len(self.roots())
    
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
    
    def __str__(self):
        return '\n'.join('{}:{}'.format(r, self.members(r)) for r in self.roots())

N, K, L = map(int, input().split())

uf = Unionfind(N)
uf1 = Unionfind(N)

for _ in range(K):
    p, q = map(int, input().split())
    uf.union(p-1, q-1)
    
for _ in range(L):
    r, s = map(int, input().split())
    uf1.union(r-1, s-1)
    
pairs = [(uf.find(i), uf1.find(i)) for i in range(N)]
#print(pairs)
    
c = Counter(pairs)
#print(c)
ans = [c[pairs[i]] for i in range(N)]

print(*ans)

N, K, L = map(int, input().split())

def fp(x, parentList): #findParent
    if parentList[x] == x:
        return x
    else:
        parentList[x] = fp(parentList[x], parentList)
        return parentList[x]

#各ノードのparentをリストで表現(連結前は自身がparent)
road = [i for i in range(N)]
rail = [i for i in range(N)]

for _ in range(K):
    p, q = map(int, input().split())
    par_p, par_q = fp(p-1, road), fp(q-1, road) #p, qのparent 
    #連結する際、若い番号をparentとする
    if par_p < par_q:
        road[par_q] = par_p
    else:
        road[par_p] = par_q

#railについても同様
for _ in range(L):
    s, t = map(int, input().split())
    par_s, par_t = fp(s-1, rail), fp(t-1, rail)
    if par_s < par_t:
        rail[par_t] = par_s
    else:
        rail[par_s] = par_t

#連結成分の要素をカウント
cnt = {}
for i in range(N):
    key = (fp(i,road),fp(i,rail))
    if key in cnt:
        cnt[key] += 1
    else:
        cnt[key] = 1
#出力
for i in range(N):
    key = (fp(i,road),fp(i,rail))
    ans = cnt[key]
    print(ans, end=" ")


from collections import Counter
n,k,l=map(int,input().split())
city1=[i for i in range(n)]
city2=[i for i in range(n)]
def root(c,x):
  if x==c[x]:
    return x
  else:
    c[x]=root(c,c[x])
    return c[x]
def union(c,x,y):
  rx=root(c,x)
  ry=root(c,y)
  if rx>ry:
    c[rx]=ry
  else:
    c[ry]=rx
for i in range(k):
  a,b=map(int,input().split())
  union(city1,a-1,b-1)
for i in range(l):
  a,b=map(int,input().split())
  union(city2,a-1,b-1)
r=[]
for i in range(n):
  r.append((root(city1,i),root(city2,i)))
c=Counter(r)
for i in range(n):
  ans=c[r[i]]
  if i==n-1:
    print(ans)
  else:
    print(ans,end=' ')

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.par = [-1]*n 
    def find(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)      
        if x==y:
            return        
        if self.par[x] > self.par[y]:
            x, y = y, x       
        self.par[x] += self.par[y]
        self.par[y] = x

N, K, L = map(int, input().split())
Uni_1 = UnionFind(N)
Uni_2 = UnionFind(N)
D = {}
for _ in range(K):
  p,q = map(int, input().split())
  Uni_1.union(p-1, q-1)
for _ in range(L):
  p,q = map(int, input().split())
  Uni_2.union(p-1, q-1)
for i in range(N):
  k = (Uni_1.find(i), Uni_2.find(i))
  if k in D.keys():
    D[k] += 1
  else:
    D[k] = 1
for i in range(N):
  print(D[(Uni_1.find(i), Uni_2.find(i))], end=" ")

from collections import Counter


class UnionFind:
    def __init__(self, n):
        self.table = [-1] * n

    def _root(self, x):
        stack = []
        tbl = self.table
        while tbl[x] >= 0:
            stack.append(x)
            x = tbl[x]
        for y in stack:
            tbl[y] = x
        return x

    def find(self, x, y):
        return self._root(x) == self._root(y)

    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.table[r1] += d2
        else:
            self.table[r1] = r2
            self.table[r2] += d1


def main():
    n, k, l = list(map(int, input().split()))
    a = UnionFind(n)
    b = UnionFind(n)
    for _ in range(k):
        p, q = list(map(int, input().split()))
        a.union(p-1, q-1)
    for _ in range(l):
        r, s = list(map(int, input().split()))
        b.union(r-1, s-1)
    d = Counter((a._root(i), b._root(i)) for i in range(n))
    print((*(d[(a._root(i), b._root(i))] for i in range(n))))


def __starting_point():
    main()

__starting_point()

from collections import Counter

class UnionFind():
  def __init__(self,n):
    self.parents=[-1]*n
  
  def find(self,x):
    if self.parents[x]<0:
      return 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
    
N,K,L=map(int,input().split())
uf_road=UnionFind(N+1)
uf_train=UnionFind(N+1)

for _ in range(K):
  p,q=map(int,input().split())
  uf_road.union(p,q)

for _ in range(L):
  s,t=map(int,input().split())
  uf_train.union(s,t)
  
union_sets=[(uf_road.find(i),uf_train.find(i)) for i in range(1,N+1)]
counts=Counter(union_sets)
ans=[counts[union_set] for union_set in union_sets]

print(' '.join(str(a) for a in ans))

import sys
readline = sys.stdin.readline
from collections import Counter

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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

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

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

def main():
    N, K, L = map(int, readline().rstrip().split())
    uf_road = UnionFind(N)
    uf_train = UnionFind(N)
    
    for _ in range(K):
        p, q = map(int, readline().rstrip().split())
        uf_road.union(p-1, q-1)
    
    for _ in range(L):
        r, s = map(int, readline().rstrip().split())
        uf_train.union(r-1, s-1)
    
    pairs = []
    for i in range(N):
        pairs.append((uf_road.find(i), uf_train.find(i)))
    
    cnt = Counter(pairs)
    res = [cnt[pair] for pair in pairs]
    print(*res)

def __starting_point():
    main()
__starting_point()

from collections import Counter

class UnionFind:
    #n個の要素を初期化
    def __init__(self, n):
        self.n = n
        self.par = [i for i in range(n)]
        self.rank = [0] * n
    
    #木の根を求める
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    
    #xとyの属する集合を併合
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    
    #xとyが同じ集合に属するか判定
    def same(self, x, y):
        return self.find(x) == self.find(y)

    #要素xが属するグループに属する要素をリストで返す
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]


N, K, L = map(int, input().split())
roads = [list(map(int, input().split())) for i in range(K)]
trains = [list(map(int, input().split())) for i in range(L)]

uf_road = UnionFind(N)
uf_train = UnionFind(N)

for road in roads:
    x, y = road
    uf_road.unite(x-1, y-1)

for train in trains:
    x, y = train
    uf_train.unite(x-1, y-1)

pairs = []
for i in range(N):
    pairs.append((uf_road.find(i), uf_train.find(i)))

cnt = Counter(pairs)

ans = [cnt[pair] for pair in pairs]
print(*ans)

# 参考URL https://note.nkmk.me/python-union-find/
class UnionFind():
    # parents
    # 各要素の親要素の番号を格納するリスト
    # 要素が根（ルート）の場合は-(そのグループの要素数)を格納する
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    # find(x)
    # 要素xが属するグループの根を返す
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    # union(x, y)
    # 要素xが属するグループと要素yが属するグループとを併合する
    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

import sys
def input():
    return sys.stdin.readline().strip()

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

road = UnionFind(n)
rail = UnionFind(n)
for _ in range(k):
    p, q = map(int, input().split())
    road.union(p-1, q-1)
for _ in range(l):
    r, s = map(int, input().split())
    rail.union(r-1, s-1)

dic = {}
l = []
for i in range(n):
    tup = (road.find(i), rail.find(i))
    l.append(tup)
    if tup in dic:
        dic[tup] += 1
    else:
        dic[tup] = 1

ans = []
for i in l:
    ans.append(dic[i])

print(' '.join(map(str, ans)))

def main():  
  #Union Find

  #xの根を求める
  def find(x):
      if par[x] < 0:
          return x
      else:
          par[x] = find(par[x])
          return par[x]
  #xとyの属する集合の併合
  def unite(x,y):
      x = find(x)
      y = find(y)

      if x == y:
          return False
      else:
          #sizeの大きいほうがx
          if par[x] > par[y]:
              x,y = y,x
          par[x] += par[y]
          par[y] = x
          return True

  def find2(x):
    if pa[x] < 0:
        return x
    else:
        pa[x] = find2(pa[x])
        return pa[x]

  import sys
  input = sys.stdin.readline

  n,k,l = [int(i) for i in input().split()]
  par = [-1]*n
  pa = [-1]*n
  ans = [0]*n

  for i in range(k):
    p,q = [int(i) for i in input().split()]
    unite(p-1,q-1)

  def unite2(x,y):
      x = find2(x)
      y = find2(y)
      if x == y:
          return False
      else:
          if pa[x] > pa[y]:
              x,y = y,x
          pa[x] += pa[y]
          pa[y] = x
          return True

  for i in range(l):
    r,s = [int(i) for i in input().split()]
    unite2(r-1,s-1)

  dic = {}
  chk = []
  for i in range(n):
      p1 = find(i)
      p2 = find2(i)
      chk.append((p1,p2))
      if (p1,p2) in dic:
          dic[(p1,p2)] += 1
      else: 
          dic[(p1,p2)] = 1
  print((' '.join([str(dic[chk[i]]) for i in range(n)])))
  
def __starting_point():
    main()

__starting_point()

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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
    def size(self, x):
        return -self.parents[self.find(x)]
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
    def group_count(self):
        return len(self.roots())
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

N,K,L=list(map(int,input().split()))
pq=[list(map(int,input().split())) for i in range(K)]
rs=[list(map(int,input().split())) for i in range(L)]

uf_road = UnionFind(N)
uf_train = UnionFind(N)

for i in range(K):
    uf_road.union(pq[i][0]-1,pq[i][1]-1)
for i in range(L):
    uf_train.union(rs[i][0]-1,rs[i][1]-1)

# 各都市に連結しているroadとtrainの積集合の探索はTLE
# ans = []
# for i in range(N):
#   ans.append(len(set(uf_road.members(i)) & set(uf_train.members(i))))
# print(*ans)

# road,trainの根のペアで同じペアを持つ都市は連結している
from collections import Counter
pair = [(uf_road.find(i), uf_train.find(i)) for i in range(N)]
ans = Counter(pair)
print(*[ans[i] for i in pair])

from collections import defaultdict


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.par = [-1] * n

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

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

    def same(self, x, y):
        return self.find(x) == self.find(y)


def main():
    n, k, l = map(int, input().split())
    
    road = UnionFind(n)
    train = UnionFind(n)
    
    for _ in range(k):
        p, q = map(int, input().split())
        road.unite(p-1, q-1)
    
    for _ in range(l):
        r, s = map(int, input().split())
        train.unite(r-1, s-1)
        
    d = defaultdict(int)
    for i in range(n):
        d[(road.find(i), train.find(i))] += 1
    
    ans = []
    for i in range(n):
        ans.append(d[(road.find(i), train.find(i))])
    
    print(*ans)


def __starting_point():
    main()
__starting_point()

import sys
from collections import defaultdict

sys.setrecursionlimit(10 ** 6)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep="\n")
def II(): return int(sys.stdin.readline())
def MI(): return map(int, sys.stdin.readline().split())
def MI1(): return map(int1, sys.stdin.readline().split())
def LI(): return list(map(int, sys.stdin.readline().split()))
def LLI(rows_number): return [LI() for _ in range(rows_number)]
def SI(): return sys.stdin.readline()[:-1]

class UnionFind:
    def __init__(self, n):
        self.state = [-1] * n
        #self.size_table = [1<<i for i in range(n)]
        # cntはグループ数
        # self.cnt = n

    def root(self, u):
        v = self.state[u]
        if v < 0: return u
        self.state[u] = res = self.root(v)
        return res

    def merge(self, u, v):
        ru = self.root(u)
        rv = self.root(v)
        if ru == rv: return
        du = self.state[ru]
        dv = self.state[rv]
        if du > dv: ru, rv = rv, ru
        if du == dv: self.state[ru] -= 1
        self.state[rv] = ru
        # self.cnt -= 1
        #self.size_table[ru] |= self.size_table[rv]
        #self.size_table[rv]=0
        return

def main():
    n,k,l=MI()
    road=UnionFind(n)
    train=UnionFind(n)
    for _ in range(k):
        u,v=MI1()
        road.merge(u,v)
    for _ in range(l):
        u,v=MI1()
        train.merge(u,v)
    cnt=defaultdict(int)
    for u in range(n):
        cnt[road.root(u),train.root(u)]+=1
    ans=[cnt[road.root(u),train.root(u)] for u in range(n)]
    print(*ans)

main()


N, M, L = [int(s) for s in input().split()]
parent_road = list(range(N))
parent_train = list(range(N))
rank_road = [0] * N
rank_train = [0] * N


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * N

    def find(self, x):
        if x == self.parent[x]:
            return x
        else:
            self.parent[x] = self.find(self.parent[x])
            return self.parent[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
        else:
            self.parent[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1


edge_road = [[int(s) - 1 for s in input().split()] for _ in range(M)]
edge_train = [[int(s) - 1 for s in input().split()] for _ in range(L)]

group_road = UnionFind(N)
group_train = UnionFind(N)

for x, y in edge_road:
    group_road.union(x, y)

for x, y in edge_train:
    group_train.union(x, y)

group_count = {}
group_list = []
for i in range(N):
    gr = group_road.find(i)
    gt = group_train.find(i)
    group_list.append((gr, gt))
    if (gr, gt) in list(group_count.keys()):
        group_count[(gr, gt)] += 1
    else:
        group_count[(gr, gt)] = 1

print((' '.join([str(group_count[g]) for g in group_list])))



# solution
import io
import math
import string

def col(n, m):
    X = [[] for _ in range(n)]
    for _ in range(m):
        a, b = map(int, input().split())
        X[a-1].append(b-1)
        X[b-1].append(a-1)
    C = [-1] * n
    c = 0
    for i in range(N):
        if C[i] >= 0: continue
        Q = [i]
        C[i] = c
        while Q:
            x = Q.pop()
            for y in X[x]:
                if C[y] == -1:
                    C[y] = C[x]
                    Q.append(y)
        c += 1
    return C

N, K, L = map(int, input().split())
A = col(N, K)
B = col(N, L)
D = {}
for a, b in zip(A, B):
    t = (a<<18) + b
    if t in D: D[t] += 1
    else: D[t] = 1

print(*[D[(a<<18)+b] for a, b in zip(A, B)])

from collections import Counter


class UnionFind:
    def __init__(self, node):
        self.parent = [-1 for _ in range(node)]
        self.node = node

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

    def is_same(self, x, y):
        return self.find(x) == self.find(y)

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

    def get_size(self, x):
        return -self.parent[self.find(x)]

    def members(self, x, is_set=False):
        root = self.find(x)
        res = [i for i in range(self.node) if self.find(i) == root]
        if is_set:
            return set(res)
        return res

    def all_root(self):
        return [idx for idx, val in enumerate(self.parent) if val < 0]


def main():
    cities, roads, railroads = list(map(int, input().split()))
    uf_road = UnionFind(cities)
    uf_train = UnionFind(cities)
    for _ in range(roads):
        p, q = [int(x) - 1 for x in input().split()]
        uf_road.union(p, q)
    for _ in range(railroads):
        r, s = [int(x) - 1 for x in input().split()]
        uf_train.union(r, s)
    each_pair = []
    for i in range(cities):
        each_pair.append(tuple([uf_road.find(i), uf_train.find(i)]))
    pair_count = dict(Counter(each_pair))
    answer = [pair_count[each_pair[i]] for i in range(cities)]
    print((" ".join(map(str, answer))))


def __starting_point():
    main()


__starting_point()

import numpy as np
from collections import Counter
from scipy.sparse.csgraph import connected_components
from scipy.sparse import csr_matrix

int1 = lambda x: int(x) - 1
N, K, L = map(int, input().split())
roads = np.array([tuple(map(int1, input().split())) for _ in range(K)]).T
railways = np.array([tuple(map(int1, input().split())) for _ in range(L)]).T


def connected(G, M):
    matr = csr_matrix((np.ones(M, dtype=int), G), shape=(N, N))
    _, labels = connected_components(matr)
    return labels


roads_connection = connected(roads, K).tolist()
railways_connection = connected(railways, L).tolist()

ct = Counter((roads_connection[i], railways_connection[i]) for i in range(N))
ans = [ct[(roads_connection[i], railways_connection[i])] for i in range(N)]
print(*ans)

from collections import Counter
n, k, l = map(int, input().split())
def find(x, par):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x], par)
        return par[x]
def unite(x, y, par):
    p = find(x, par)
    q = find(y, par)
    if p == q:
        return None
    if p > q:
        p, q = q, p
    par[p] += par[q]
    par[q] = p
def same(x, y):
    return find(x) == find(y)
def size(x):
    return -par[find(x)]
road_par = [-1 for i in range(n + 1)]
train_par = [-1 for i in range(n + 1)]
for i in range(k):
    p, q = map(int, input().split())
    unite(p, q, road_par)
for i in range(l):
    r, s = map(int, input().split())
    unite(r, s, train_par)
ans = []
for i in range(n):
    ans.append((find(i + 1, road_par), find(i + 1, train_par)))
c = Counter(ans)
for i in ans:
    print(c[i], end=" ")

from sys import stdin
import sys
import math
from functools import reduce
import functools
import itertools
from collections import deque,Counter
from operator import mul
import copy

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

road = [[] for i in range(n+1)]
rail = [[] for i in range(n+1)]

for i in range(k):
    p, q = list(map(int, input().split()))
    road[p].append(q)
    road[q].append(p)

for i in range(l):
    r, s = list(map(int, input().split()))
    rail[r].append(s)
    rail[s].append(r)

seen = [0 for i in range(n+1)]

def dfs_stack(u, al, al_c, d):
    stack = deque([u])
    seen[u] = 1

    while len(stack) > 0:
        v = stack.pop()
        ###
        al_c[v] = d
        ###

        for w in al[v]:
            if seen[w] == 0:
                stack.append(w)
                seen[w] = 1

        if stack == []: break


road_c = [-1 for i in range(n+1)]
rail_c = [-1 for i in range(n+1)]

d = 0
for i in range(1,n+1):
    if seen[i] == 0:
        dfs_stack(i, road, road_c, d)
        d += 1

seen = [0 for i in range(n+1)]

d = 0
for i in range(1,n+1):
    if seen[i] == 0:
        dfs_stack(i, rail, rail_c, d)
        d += 1

dict = {}

for i in range(1, n+1):
    if (road_c[i], rail_c[i]) not in dict:
        dict[(road_c[i], rail_c[i])] = [i]
    else:
        dict[(road_c[i], rail_c[i])].append(i)

ans = [0 for i in range(n+1)]

for dd in list(dict.items()):
    for j in dd[1]:
        ans[j] = str(len(dd[1]))

print((' '.join(ans[1:])))


#UNIONFIND
class UnionFind:
    def __init__(self, n):
        # 負  : 根であることを示す。絶対値はランクを示す
        # 非負: 根でないことを示す。値は親を示す
        self.table = [-1] * n
 
    def _root(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self._root(self.table[x])
            return self.table[x]
 
    def find(self, x, y):
        return self._root(x) == self._root(y)
 
    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        # ランクの取得
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2
 
 
def __starting_point():
    n,k,l=map(int,input().split())
    pq=UnionFind(n+1)
    rs=UnionFind(n+1)
    for i in range(k):
        p,q=map(int,input().split())
        pq.union(p,q)
    for i in range(l):
        r,s=map(int,input().split())
        rs.union(r,s)
    sameroot=[]
    for i in range(1,n+1):
        sameroot.append([pq._root(i),rs._root(i),i])
    sameroot.sort()
    sameroot.append([0,0,n+1])
    cnt=[0]*(n+1)
    bx,by=0,0
    samelist=[]
    for x,y,i in sameroot:
        if bx==x and by==y:
            samelist.append(i)
        else:
            k=len(samelist)
            if k>0:
                for j in samelist:
                    cnt[j]=k
            samelist=[i]
            bx,by=x,y
    print(' '.join(map(str,cnt[1:])))
__starting_point()

import sys
import heapq, math
from itertools import zip_longest, permutations, combinations, combinations_with_replacement
from itertools import accumulate, dropwhile, takewhile, groupby
from functools import lru_cache
from copy import deepcopy


class UnionFind:

    def __init__(self, n: int):
        self._n = n
        self._parents = [i for i in range(n)]
        self._size = [1 for _ in range(n)]

    def unite(self, x: int, y: int) -> None:
        px = self.find(x)
        py = self.find(y)

        # 一致していないときはリンクをつける
        if px != py:
            self._link(px, py)

    def _link(self, x: int, y: int):
        if self._size[x] < self._size[y]:
            self._parents[x] = y
            self._size[y] += self._size[x]
        else:
            self._parents[y] = x
            self._size[x] += self._size[y]

    def same(self, x: int, y: int) -> bool:
        px = self.find(x)
        py = self.find(y)
        return px == py

    def find(self, x: int) -> int:
        if self._parents[x] == x:
            return x

        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]

    def size(self, x: int):
        return self._size[self.find(self._parents[x])]

N, K, L = map(int, input().split())

road = UnionFind(N + 1)
rail = UnionFind(N + 1)
share = UnionFind(N + 1)

roads = [list(map(int, input().split())) for _ in range(K)]
rails = [list(map(int, input().split())) for _ in range(L)]

for i in range(K):
    p, q = roads[i]
    road.unite(p, q)

for i in range(L):
    r, s = rails[i]
    rail.unite(r, s)

m = {}

for i in range(1, N + 1):
    cnt = m.get((road.find(i), rail.find(i)), 0)
    m[(road.find(i), rail.find(i))] = cnt + 1

ans = [0] * N
for i in range(N):
    ans[i] = m[(road.find(i + 1), rail.find(i + 1))]

print(*ans)

import collections
class UnionFind:
    def __init__(self,n):
        super().__init__()
        self.par = [-1]*n
        self.rank = [0]*n
        self.tsize = [1]*n

    
    def root(self,x):
        if self.par[x] == -1:
            return x 
        else:
            self.par[x] = self.root(self.par[x])
            return self.par[x]

    def unite(self, x, y):
        x_r = self.root(x)
        y_r = self.root(y)
        
        if self.rank[x_r]>self.rank[y_r]:
            self.par[y_r] = x_r

        elif self.rank[x_r]<self.rank[y_r]:
            self.par[x_r] = y_r

        elif x_r != y_r:
            self.par[y_r] = x_r
            self.rank[x_r] += 1

        if x_r != y_r:
            size = self.tsize[x_r]+self.tsize[y_r]
            self.tsize[x_r] = size
            self.tsize[y_r] = size

    def isSame(self,x,y):
        return self.root(x) == self.root(y)

    def size(self,x):
        return self.tsize[self.root(x)]

def main():
    n,k,l = tuple([int(t)for t in input().split()])

    uf_k = UnionFind(n)
    uf_l = UnionFind(n)


    pq = [[int(t)-1 for t in input().split()]for _ in [0]*k]
    for p,q in pq:
        uf_k.unite(p,q)

    rs = [[int(t)-1 for t in input().split()]for _ in [0]*l]
    for r,s in rs:
        uf_l.unite(r,s)

    pair = []
    for i in range(n):
        pair.append((uf_k.root(i),uf_l.root(i)))
    counter = collections.Counter(pair)
    
    ans = []
    for a in pair:
        ans.append(counter[a])
    print(*ans)
    
def __starting_point():
    main()
__starting_point()

from collections import *
N, K, L = list(map(int,input().split()))

def f(m):
    *a, = list(range(N))
    def g(i):
        if a[i] == i:
            return i
        a[i] = g(a[i])
        return a[i]
    for _ in range(m):
        p, q = list(map(int,input().split()))
        a[g(q-1)] = g(p-1)
    return g

x, y = f(K), f(L)
c = Counter((x(i),y(i)) for i in range(N))
print((*((c[x(i),y(i)]) for i in range(N))))


class UnionFind(object):
    def __init__(self, n=1):
        self.par = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        self.size = [1 for _ in range(n)]
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.par[y] = x
            self.size[x] += self.size[y]
    def is_same(self, x, y):
        return self.find(x) == self.find(y)
    def get_size(self, x):
        x = self.find(x)
        return self.size[x]
import collections
N,K,L=map(int,input().split())
uf1=UnionFind(N)
for i in range(K):
  p,q=map(int,input().split())
  uf1.union(p-1,q-1)
uf2=UnionFind(N)
for j in range(L):
  r,s=map(int,input().split())
  uf2.union(r-1,s-1)
list=[]
for i in range(N):
  list.append((uf1.find(i),uf2.find(i)))
count=collections.Counter(list)
for i in range(N):
  ans=count[list[i]]
  if i==N-1:
    print(ans)
  else:
    print(ans,end=' ')

import sys

sys.setrecursionlimit(10 ** 6)
INF = float("inf")
MOD = 10 ** 9 + 7


def input():
    return sys.stdin.readline().strip()


class UnionFind:
    def __init__(self, n_nodes):
        self.n_nodes = n_nodes
        self.parents = [-1] * n_nodes

    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 unite(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

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

    def check(self, x, y):
        return self.find(x) == self.find(y)

    def get_parent_list(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def get_members(self, x):
        parent = self.find(x)
        return [i for i in range(self.n_nodes) if self.find(i) == parent]

    def get_members_dict(self):
        return {par: self.get_members(par) for par in self.get_parent_list()}


def main():
    N, K, L = map(int, input().split())
    tree_road = UnionFind(N)
    tree_subway = UnionFind(N)

    for _ in range(K):
        p, q = map(int, input().split())
        p -= 1
        q -= 1
        tree_road.unite(p, q)

    for _ in range(L):
        r, s = map(int, input().split())
        r -= 1
        s -= 1
        tree_subway.unite(r, s)

    d = {}
    for i in range(N):
        p1 = tree_road.find(i)
        p2 = tree_subway.find(i)
        if (p1, p2) not in d:
            d[(p1, p2)] = 1
        else:
            d[(p1, p2)] += 1

    for i in range(N):
        p1 = tree_road.find(i)
        p2 = tree_subway.find(i)
        print(d[(p1, p2)], end=" ")


def __starting_point():
    main()

__starting_point()

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
from collections import defaultdict

N, K, L = list(map(int, input().split()))
G1 = [[] for i in range(N)]
for i in range(K):
    p, q = list(map(int, input().split()))
    p -= 1
    q -= 1
    G1[p].append(q)
    G1[q].append(p)
gids = [0]*N
done = [False]*N
def dfs1(i, gid):
    gids[i] = gid
    done[i] = True
    for nex in G1[i]:
        if done[nex]: continue
        dfs1(nex, gid)
gid = 0
for i in range(N):
    if not done[i]:
        dfs1(i, gid)
        gid += 1

G = [[] for i in range(N)]
for i in range(L):
    r, s = list(map(int, input().split()))
    r -= 1
    s -= 1
    G[r].append(s)
    G[s].append(r)
done = [False]*N
D = []
gid = 0
def dfs(i, gid):
    D[gid][gids[i]] += 1
    done[i] = True
    for nex in G[i]:
        if done[nex]: continue
        dfs(nex, gid)
for i in range(N):
    if not done[i]:
        D.append(defaultdict(int))
        dfs(i, gid)
        gid += 1
ans = [0]*N
done = [False]*N
gid = 0
def dfs2(i, gid):
    done[i] = True
    ans[i] = D[gid][gids[i]]
    for nex in G[i]:
        if done[nex]: continue
        dfs2(nex, gid)
for i in range(N):
    if not done[i]:
        dfs2(i, gid)
        gid += 1
print((*ans))


from collections import Counter


class UnionFind:

    def __init__(self, n: int) -> None:
        self.parent = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]

    def find(self, i: int) -> None:
        if self.parent[i] == i:
            return i
        else:
            return self.find(self.parent[i])

    def unite(self, i: int, j: int) -> None:
        root_i = self.find(i)
        root_j = self.find(j)
        if root_i == root_j:
            return
        if self.rank[root_i] < self.rank[root_j]:
            self.parent[root_i] = root_j
        else:
            self.parent[root_j] = root_i
            if self.rank[root_i] == self.rank[root_j]:
                self.rank[root_i] += 1

                
N, K, L = map(int, input().split())

uf1 = UnionFind(N)
for _ in range(K):
    i, j = map(int, input().split())
    uf1.unite(i - 1, j - 1)

uf2 = UnionFind(N)
for _ in range(L):
    i, j = map(int, input().split())
    uf2.unite(i - 1, j - 1)

set_id_pairs = [(uf1.find(i), uf2.find(i)) for i in range(N)]
counter = Counter(set_id_pairs)
counts = [counter[set_id_pairs[i]] for i in range(N)]
print(' '.join(str(c) for c in counts))

"""
in1 = '7 4 4'
in2 = ['1 2', '2 3', '2 5', '6 7', '3 5', '4 5', '3 4', '6 7']
N, K, L = map(int, in1.split())
pqrs = []
for idx1 in range(K + L):
    temp0, temp1 = map(int, in2[idx1].split())
    pqrs.append([temp0, temp1])
"""

def makeTree(a):
    aT = list(range(N + 1))
    for p, q in a:
        rootp     = getRoot(aT, p)
        rootq     = getRoot(aT, q)
        thisRoot  = max(rootp, rootq, q)
        aT[p]     = thisRoot
        aT[q]     = thisRoot
        aT[rootp] = thisRoot
        aT[rootq] = thisRoot
    return aT

def getRoot(a,i):
    if a[i] == i:
        return i
    else:
        a[i] = getRoot(a, a[i])
        return a[i]

N, K, L = list(map(int, input().split()))
pqrs = []
for idx1 in range(K + L):
    temp0, temp1 = list(map(int, input().split()))
    pqrs.append([temp0, temp1])

MTree = makeTree(pqrs[0:K])
TTree = makeTree(pqrs[K:])

aRet = []
dRet = {}
for idx1 in range(1, N + 1):
    Comb = (getRoot(MTree, idx1), getRoot(TTree, idx1))
    aRet.append(Comb)
    if Comb in dRet:
        dRet[Comb] += 1
    else:
        dRet[Comb] = 1

print((" ".join([str(dRet[_]) for _ in aRet])))


import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
from collections import defaultdict

# UnionFind
class UnionFind:
    def __init__(self, n):
        self.parent = [i for i in range(n)]

    def root(self, x):
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.root(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x != y:
            self.parent[x] = y

    def same(self, x, y):
        return self.root(x) == self.root(y)

N, K, L = list(map(int, input().split()))
un = UnionFind(N)
for i in range(K):
    p, q = list(map(int, input().split()))
    p -= 1
    q -= 1
    un.unite(p, q)
G = [[] for i in range(N)]
for i in range(L):
    r, s = list(map(int, input().split()))
    r -= 1
    s -= 1
    G[r].append(s)
    G[s].append(r)
done = [False]*N
D = []
gid = 0
def dfs(i, gid):
    D[gid][un.root(i)] += 1
    done[i] = True
    for nex in G[i]:
        if done[nex]: continue
        dfs(nex, gid)
for i in range(N):
    if not done[i]:
        D.append(defaultdict(int))
        dfs(i, gid)
        gid += 1
ans = [0]*N
done = [False]*N
gid = 0
def dfs2(i, gid):
    done[i] = True
    ans[i] = D[gid][un.root(i)]
    for nex in G[i]:
        if done[nex]: continue
        dfs2(nex, gid)
for i in range(N):
    if not done[i]:
        dfs2(i, gid)
        gid += 1
print((*ans))


from collections import deque

n,k,l = map(int,input().split())
ep = [[] for i in range(n)]
er = [[] for i in range(n)]

gp = [-1]*n
gr = [-1]*n

for i in range(k):
    a,b = map(int,input().split())
    a -= 1
    b -= 1
    ep[a].append(b)
    ep[b].append(a)
for i in range(l):
    a,b = map(int,input().split())
    a -= 1
    b -= 1
    er[a].append(b)
    er[b].append(a)

def dfs(e,g):
    count = 0
    for i in range(n):
        if g[i] == -1:
            g[i] = count

            q = deque([])
            q.append(i)
            while q:
                now = q.pop()

                for nex in e[now]:
                    if g[nex] == -1:
                        g[nex] = g[now]
                        q.append(nex)
            count += 1

    return g
gp = dfs(ep,gp)
gr = dfs(er,gr)
l = []
dic = {}
for i in range(n):
    s = (gp[i],gr[i])
    l.append(s)
    if s in dic:
        dic[s] += 1
    else:
        dic[s] = 1
ans = [0]*n

for i in range(n):
    ans[i] = dic[l[i]]
print(*ans)

n,k,l=map(int,input().split())
class UnionFind:
    #def   -> foo=UnionFind(n,1)  <- 1-based index, default is 0
    #method -> foo.hoge(huga)
    __slots__ = ["_size", "_first_idx", "_parents"]
    def __init__(self, size: int, first_index: int = 0) -> None:
        self._size = size
        self._first_idx = first_index
        self._parents = [-1] * (size + first_index)
    def find(self, x: int) -> int:
        if self._parents[x] < 0:
            return x
        news=[]
        p=self._parents
        y=p[x]
        while y>=0:
            news.append(x);x,y=y,p[y]
        if len(news)!=1:
            for P in news:p[P]=x
        return x

    def same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)
    def unite(self, x: int, y: int) -> bool:
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        if self._parents[x] > self._parents[y]:
            x, y = y, x
        self._parents[x] += self._parents[y]
        self._parents[y] = x
        return True
    def size(self, x: int) -> int:
        return -self._parents[self.find(x)]
    def group_count(self) ->int:
        return sum(1 for i in  self._parents if i<0)-self._first_idx
    def connected(self) ->bool:
        return self._parents[self.find(self._first_idx)]==-self._size
road=UnionFind(1,n)
rail=UnionFind(1,n)

for i in range(k):
    road.unite(*map(int,input().split()))
for i in range(l):
    rail.unite(*map(int,input().split()))
from collections import defaultdict
d=defaultdict(int)

for i in range(1,n+1):
    ap,op=rail.find(i),road.find(i)
    d[ap*(n+1)+op]+=1
print(*[d[road.find(i)+rail.find(i)*(n+1)]for i in range(1,n+1)])

import sys

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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

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

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


N, K, L = map(int,input().split())
uf_road = UnionFind(N)
uf_train = UnionFind(N)

for i in range(K):
    p,q = map(int,input().split())
    p -= 1
    q -= 1
    uf_road.union(p,q)

for i in range(L):
    p,q = map(int,input().split())
    p -= 1
    q -= 1
    uf_train.union(p,q)

pair_list = []
for i in range(N):
    pair_list.append((uf_road.find(i), uf_train.find(i), i))

pair_list.sort()
ans = [0] * N

pair = (pair_list[0][0], pair_list[0][1])
countup_list = [pair_list[0][2]]
for i in range(1,N):
    if pair == (pair_list[i][0], pair_list[i][1]):
        countup_list.append(pair_list[i][2])
    else:
        for c in countup_list:
            ans[c] += len(countup_list)
        pair = (pair_list[i][0], pair_list[i][1])
        countup_list = [pair_list[i][2]]

for c in countup_list:
    ans[c] += len(countup_list)
    
for i in range(N):
    print(ans[i], end=" ")

import sys
from collections import defaultdict
input = sys.stdin.readline


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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

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

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


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


import sys
sys.setrecursionlimit(10**7)
from collections import Counter
class UnionFind():
    def __init__(self,n):
        self.n = n
        self.parents = [-1]*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
    #木の深さじゃなくxを含む集合の要素数
    def size(self,x):
        return -self.parents[self.find(x)]

    def same(self,x,y):
        return self.find(x)==self.find(y)

    def members(self,x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root]

    def roots(self):
        return [i for i,x in enumerate(self.parents) if x>0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
n,k,l=map(int,input().split())
load=UnionFind(n+1)
tetsu=UnionFind(n+1)
for _ in range(k):
    p,q=map(int,input().split())
    load.union(p,q)
for _ in range(l):
    r,s = map(int,input().split())
    tetsu.union(r,s)

count = [(load.find(i),tetsu.find(i)) for i in range(1,n+1)]
# print(count)
C = Counter(count)
ans = []
for i in range(n):
	if count[i][0]<0 or count[i][1]<0:
		ans.append(0)
	else:
		ans.append(C[count[i]])
print(*ans)

n,k,l=map(int,input().split())
load=[[] for _ in range(n)]
train=[[] for _ in range(n)]
for _ in range(k):
  a,b=map(int,input().split())
  a-=1
  b-=1
  load[a].append(b)
  load[b].append(a)
for _ in range(l):
  a,b=map(int,input().split())
  a-=1
  b-=1
  train[a].append(b)
  train[b].append(a)

# 道路の連結グループ
load_grp_id=[-1]*n
not_grp=set(range(n))
while not_grp:
  t0=not_grp.pop()
  todo=[t0]
  load_grp_id[t0]=t0
  while todo:
    t=todo.pop()
    l=load[t]
    for li in l:
      if load_grp_id[li]==-1:
        load_grp_id[li]=t0
        not_grp.discard(li)
        todo.append(li)
# 鉄道の連結グループ
train_grp_id=[-1]*n
not_grp=set(range(n))
while not_grp:
  t0=not_grp.pop()
  todo=[t0]
  train_grp_id[t0]=t0
  while todo:
    t=todo.pop()
    l=train[t]
    for li in l:
      if train_grp_id[li]==-1:
        train_grp_id[li]=t0
        not_grp.discard(li)
        todo.append(li)

d={}
for i in range(n):
  lid=load_grp_id[i]
  tid=train_grp_id[i]
  if (lid,tid) in d:
    d[(lid,tid)]+=1
  else:
    d[(lid,tid)]=1
ans=[]
for i in range(n):
  lid=load_grp_id[i]
  tid=train_grp_id[i]
  ans.append(str(d[(lid,tid)]))
print(' '.join(ans))

from collections import defaultdict
class UnionFind():
  def __init__(self,n):
    self.n=n
    self.parents=[-1]*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 unite(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
  def size(self,x):
    return -size.parents[self.find(x)]
  def same(self,x,y):
    return self.find(x)==self.find(y)
  def members(self,x):
    root=self.find(x)
    return [i for i in range(self.n) if self.find(i)==root]
  def roots(self):
    return [i for i,x in enumerate(self.parents) if x<0]
  def group_count(self):
    return len(self.roots())
  def all_group_members(self):
    return {r:self.members(r) for r in self.roots()}
n,k,l=map(int,input().split())
uf1=UnionFind(n)
for _ in range(k):
  u,v=map(int,input().split())
  uf1.unite(u-1,v-1)
uf2=UnionFind(n)
for _ in range(l):
  u,v=map(int,input().split())
  uf2.unite(u-1,v-1)
d=defaultdict(int)
for i in range(n):
  d[(uf1.find(i),uf2.find(i))]+=1
ans=[d[(uf1.find(i),uf2.find(i))] for i in range(n)]
print(*ans)

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
from collections import defaultdict

N, K, L = list(map(int, input().split()))

# Group1
G1 = [[] for i in range(N)]
for i in range(K):
    p, q = list(map(int, input().split()))
    p -= 1
    q -= 1
    G1[p].append(q)
    G1[q].append(p)
gids = [0]*N
done = [False]*N
def dfs1(i, gid):
    gids[i] = gid
    done[i] = True
    for nex in G1[i]:
        if done[nex]: continue
        dfs1(nex, gid)
gid = 0
for i in range(N):
    if not done[i]:
        dfs1(i, gid)
        gid += 1

# Group2
G = [[] for i in range(N)]
for i in range(L):
    r, s = list(map(int, input().split()))
    r -= 1
    s -= 1
    G[r].append(s)
    G[s].append(r)
done = [False]*N
D = []
gids2 = [0]*N
def dfs(i, gid):
    D[gid][gids[i]] += 1
    done[i] = True
    gids2[i] = gid
    for nex in G[i]:
        if done[nex]: continue
        dfs(nex, gid)
gid = 0
for i in range(N):
    if not done[i]:
        D.append(defaultdict(int))
        dfs(i, gid)
        gid += 1

# answer
ans = [0]*N
for i in range(N):
    ans[i] = D[gids2[i]][gids[i]]
print((*ans))


import sys
from collections import deque
from collections import defaultdict
from collections import Counter

def conn(n,m,e):
    d=dict(list(zip(list(range(1,n+1)),list(range(-1,(-1)*n-1,-1)))))
    td=defaultdict(lambda:deque([])) #tdは同値類がキーで中の元が値
    c=1
    for edge in e:
        a=edge[0]
        b=edge[1]
        da=d[a] #da,dbはa,bの含まれる同値流のラベル
        db=d[b]
        if da<0 and db<0:
            d[a]=c
            d[b]=c
            td[c].append(a)
            td[c].append(b)
            c+=1
        elif da>0 and db<0:
            d[b]=da
            td[d[a]].append(b)
        elif da<0 and db>0:
            d[a]=db
            td[d[b]].append(a)
        elif da>0 and db>0 and da!=db:
            for x in td[db]:
                d[x]=da
                td[da].append(x)

    return list(d.values())

def components(n,k,e):
    ed=defaultdict(lambda:deque())
    for edge in e:
        ed[edge[0]].append(edge[1])
    c=0
    s=[0]*n
    label=[0]*n
    for i in range(1,n+1):
        if s[i-1]==0:
            c+=1
            label[c-1]=c
            stack=deque([i])
            while stack:
                w=stack.pop()
                s[w-1]=c
                while ed[w]:
                    wn=ed[w].pop()
                    if s[wn-1]==0:
                        s[wn-1]=c
                        if ed[wn]:
                            stack.append(w)
                            w=wn
                    elif s[wn-1]<c:
                        label[s[wn-1]-1]=c
    return [label[s[i]-1] for i in range(n)] 
           
def components2(n,k,e):
    ed=defaultdict(lambda:deque())
    for edge in e:
        ed[edge[0]].append(edge[1])
        ed[edge[1]].append(edge[0])
    c=0
    s=[0]*n
    for i in range(1,n+1):
        if s[i-1]==0:
            c+=1
            stack=deque([i])
            while stack:
                w=stack.pop()
                s[w-1]=c
                while ed[w]:
                    wn=ed[w].pop()
                    if s[wn-1]==0:
                        s[wn-1]=c
                        if ed[wn]:
                            stack.append(w)
                            w=wn
    return [s[i] for i in range(n)] 
def main(n,k,l,e1,e2):
    d1=components2(n,k,e1)
    d2=components2(n,l,e2)
    p=tuple(zip(iter(d1),iter(d2)))
    d=Counter(p)
    # print(d1,d2,d,p)
    print((' '.join([str(d[x]) for x in p]))) 

def __starting_point():
    ssr=sys.stdin.readline
    n,k,l=list(map(int,ssr().strip().split()))
    e1=[]
    e2=[]
    for _ in range(k):
        e1.append(tuple(map(int,ssr().strip().split())))
    for _ in range(l):
        e2.append(tuple(map(int,ssr().strip().split())))
    main(n,k,l,e1,e2)

__starting_point()

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
from collections import defaultdict

# UnionFind
class UnionFind:
    def __init__(self, n):
        self.parent = [i for i in range(n)]

    def root(self, x):
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.root(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x != y:
            self.parent[x] = y

    def same(self, x, y):
        return self.root(x) == self.root(y)

N, K, L = list(map(int, input().split()))
un1 = UnionFind(N)
for i in range(K):
    p, q = list(map(int, input().split()))
    p -= 1
    q -= 1
    un1.unite(p, q)
un2 = UnionFind(N)
for i in range(L):
    r, s = list(map(int, input().split()))
    r -= 1
    s -= 1
    un2.unite(r, s)
dic = defaultdict(int)
for i in range(N):
    a, b = un1.root(i), un2.root(i)
    k = str(a)+":"+str(b)
    dic[k] += 1

ans = [0]*N
for i in range(N):
    a, b = un1.root(i), un2.root(i)
    k = str(a)+":"+str(b)
    ans[i] = dic[k]
print((*ans))


from collections import defaultdict


class UnionFind:

    def __init__(self, n):
        # * Access m-th node by index `m`, not `m - 1`.
        self.parents = [i for i in range(n + 1)]
        self.ranks = [0 for _ in range(n + 1)]

    def find_root(self, node):
        parent_node = self.parents[node]
        if parent_node == node:
            return node
        else:
            root_node = self.find_root(parent_node)
            self.parents[node] = root_node  # reduction
            return root_node

    def union(self, one, other):
        one_root = self.find_root(one)
        other_root = self.find_root(other)
        if one_root == other_root:
            return
        if self.ranks[one_root] < self.ranks[other_root]:
            self.parents[one_root] = other_root
        else:
            self.parents[other_root] = one_root
            if self.ranks[one_root] == self.ranks[other_root]:
                self.ranks[one_root] += 1

    def is_same_group(self, one, other):
        one_root = self.find_root(one)
        other_root = self.find_root(other)
        return one_root == other_root


def main():
    N, K, L = list(map(int, input().split(' ')))
    road_tree = UnionFind(N)
    for _ in range(K):
        p, q = list(map(int, input().split(' ')))
        road_tree.union(p, q)
    train_tree = UnionFind(N)
    for _ in range(L):
        r, s = list(map(int, input().split(' ')))
        train_tree.union(r, s)
    # Calculate groups
    group_count = defaultdict(int)
    group_list = list()
    for node in range(1, N + 1):
        group = (road_tree.find_root(node), train_tree.find_root(node))
        group_count[group] += 1
        group_list.append(group)
    answer = ' '.join(list(map(
        lambda g: str(group_count[g]),
        group_list
    )))
    print(answer)


def __starting_point():
    main()
__starting_point()

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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
    def size(self, x):
        return -self.parents[self.find(x)]
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
    def group_count(self):
        return len(self.roots())
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

def main():
    n, k, l = map(int, input().split())
    p = [list(map(int, input().split())) for _ in range(k)]
    r = [list(map(int, input().split())) for _ in range(l)]
    uf1 = UnionFind(n)
    for a, b in p:
        uf1.union(a-1, b-1)
    uf2 = UnionFind(n)
    for a, b in r:
        uf2.union(a-1, b-1)
    dic = {}
    for i in range(n):
        rt1, rt2 = uf1.find(i), uf2.find(i)
        if (rt1, rt2) in dic:
            dic[(rt1, rt2)] += 1
        else:
            dic[(rt1, rt2)] = 1
    for i in range(n):
        rt1, rt2 = uf1.find(i), uf2.find(i)
        print(dic[(rt1, rt2)], end=" ")

def __starting_point():
    main()
__starting_point()

from collections import Counter

class UnionFind():
  def __init__(self,n):
    self.parents=[-1]*n
  
  def find(self,x):
    if self.parents[x]<0:
      return 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
    
  def size(self,x):
    return abs(self.parents[self.find(x)])
  

N,K,L=list(map(int,input().split()))
uf_road=UnionFind(N+1)
uf_train=UnionFind(N+1)
road_dict=dict()
train_dict=dict()

for _ in range(K):
  p,q=list(map(int,input().split()))
  uf_road.union(p,q)

for _ in range(L):
  r,s=list(map(int,input().split()))
  uf_train.union(r,s)

set_id_pairs = [(uf_road.find(i), uf_train.find(i)) for i in range(1,N+1)]
counter = Counter(set_id_pairs)
counts = [counter[set_id_pairs[i]] for i in range(N)]
print((' '.join(str(c) for c in counts)))


import sys
mod=10**9+7 ; inf=float("inf")
from math import sqrt, ceil
from collections import deque, Counter, defaultdict #すべてのkeyが用意されてる defaultdict(int)で初期化
input=lambda: sys.stdin.readline().strip()
sys.setrecursionlimit(11451419)
from decimal import ROUND_HALF_UP,Decimal  #変換後の末尾桁を0や0.01で指定
  #Decimal((str(0.5)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
from functools import lru_cache
from bisect import bisect_left as bileft, bisect_right as biright
#メモ化再帰defの冒頭に毎回 @lru_cache(maxsize=10**10)
#引数にlistはだめ
#######ここまでテンプレ#######
#ソート、"a"+"b"、再帰ならPython3の方がいい
#######ここから天ぷら########
class UnionFind():
    def __init__(self,num):
        self.n = num         #class内変数nに、外部から入力した値numを代入
        self.parents = [-1 for i in range(self.n)]
          #parentsは要素の親(1こ上のやつ)番号0~n-1を格納、自分が最親なら-(要素数)を格納(初期値は-1)

    #xの最親は誰？
    def find(self,x):
        if self.parents[x]<0:
            return x
        else:
            self.parents[x]=self.find(self.parents[x]) #再帰して1番上までいってる
                #調べながらparentsの値を更新してる！（経路圧縮）
            return self.parents[x]

    #結合せよ
    #xの親とyの親をくっつける
    def union(self,x,y):
        xx=self.find(x)  #xxはxの最親
        yy=self.find(y)  #yyはyの最親
        if xx==yy:
            return     #同じ屋根の下にあった場合は何もしない
        else:
            size_xx=abs(self.parents[xx]) #xが含まれる木のサイズ
            size_yy=abs(self.parents[yy]) #yが含まれる木のサイズ
            if size_xx>size_yy:
                xx,yy=yy,xx  #yyの方が大きい木、ってことにする

            self.parents[yy]+=self.parents[xx] #大きい木のサイズ更新
            self.parents[xx]=yy   #サイズが小さい木を大きい木に接ぐ

    #xの属する木の大きさ（まあunionでも使ったけど）
    def size(self,x):
        xx=self.find(x)
        return abs(self.parents[xx])

    #xとyはこの空の続く場所にいますか　いつものように笑顔でいてくれますか　今はただそれを願い続ける
    def same(self,x,y):
        return 1 if self.find(x)==self.find(y) else 0

    #xと　同じ木にいる　メンバーは？
    def members(self,x):
        xx=self.find(x)
        return [i for i in range(self.n) if self.find(i)==xx]
             #ifの条件式に漏れたら無視

    #最親だけを並べあげる
    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0]
        #いやこれは天才すぎる、basisのenumerate.py参照

    #すべての最親について、メンバーを辞書で
    def all_group_members(self):
        return {r:self.members(r) for r in self.roots()}

    #グループ分けどうなりましたか、２重リストで
    def state_grouping(self):
        return list(self.all_group_members().values())

n,k,l=map(int,input().split())
uf=UnionFind(n)
uf2=UnionFind(n)
for i in range(k):
    p,q=map(int,input().split())
    p-=1;q-=1
    uf.union(p,q)
for i in range(l):
    p,q=map(int,input().split())
    p-=1;q-=1
    if 1:
        uf2.union(p,q)

C= Counter( [ ( uf.find(i),uf2.find(i) ) for i in range(n)] )
ANS=[0]*n 
for i in range(n):
    ANS[i]= C[(uf.find(i),uf2.find(i))]
print(*ANS)

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n
        self.group_count = 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

        self.group_count -= 1

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

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

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

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

def int_(num_str):
    return int(num_str) - 1


N, K, L = list(map(int, input().split()))
uf1 = UnionFind(N)
for _ in range(K):
    p, q = list(map(int_, input().split()))
    uf1.union(p, q)
uf2 = UnionFind(N)
for _ in range(L):
    r, s = list(map(int_, input().split()))
    uf2.union(r, s)
from collections import Counter
pair = [(uf1.find(i), uf2.find(i)) for i in range(N)]
ans = Counter(pair)
print((*[ans[p] for p in pair]))


class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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
    def size(self, x):
        return -self.parents[self.find(x)]
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
    def group_count(self):
        return len(self.roots())
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

from collections import Counter
n, k, l = map(int, input().split())
a = [list(map(int, input().split())) for i in range(k)]
b = [list(map(int, input().split())) for i in range(l)]
uf1 = UnionFind(n)
uf2 = UnionFind(n)
for i in a:
	uf1.union(i[0]-1, i[1]-1)
for i in b:
	uf2.union(i[0]-1, i[1]-1)
l = [[0, 0] for i in range(n)]
for i in range(n):
	l[i][0] = uf1.find(i)
	l[i][1] = uf2.find(i)
	l[i] = tuple([l[i][0], l[i][1]])
c = Counter(l)
for i in range(n):
	print(c[l[i]],end=" ")

from collections import defaultdict
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):  #要素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が属するグループと要素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

    def size(self, x):  #グループのサイズ
        return -self.parents[self.find(x)]

    def same(self, x, y):   #要素xと要素yが同じグループかどうか
        return self.find(x) == self.find(y)

    def members(self, x):   #要素xが属するグループに属する要素をリストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):    #すべての根の要素をリストで返す
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):  #グループの数を変えす
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

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

uf = UnionFind(n)

p, q = [0] * k, [0] * k
for i in range(k):
    pp, qq = map(int, input().split())
    p[i] = pp - 1 
    q[i] = qq - 1
    uf.union(pp - 1, qq - 1)

uuff = UnionFind(n)
r, s = [0] * l, [0] * l
for i in range(l):
    rr, ss = map(int, input().split())
    r[i] = rr - 1
    s[i] = ss - 1
    uuff.union(rr - 1, ss - 1)
dic = defaultdict(int)
for i in range(n):
    dic[(uf.find(i), uuff.find(i))] += 1

ans = []
for i in range(n):
    ans.append(dic[uf.find(i), uuff.find(i)])

for i in ans:
    print(i,end=" ")

from collections import Counter

n,k,l=map(int,input().split())
city1=[i for i in range(n)]
city2=[i for i in range(n)]

def root(c,x):
  if x==c[x]:
    return x
  else:
    c[x]=root(c,c[x])
    return c[x]

def union(c,x,y):
  rx=root(c,x)
  ry=root(c,y)
  if rx>ry:
    c[rx]=ry
  else:
    c[ry]=rx

for i in range(k):
  a,b=map(int,input().split())
  union(city1,a-1,b-1)
for i in range(l):
  a,b=map(int,input().split())
  union(city2,a-1,b-1)
r=[]
for i in range(n):
  r.append((root(city1,i),root(city2,i)))
c=Counter(r)
for i in range(n):
  ans=c[r[i]]
  if i==n-1:
    print(ans)
  else:
    print(ans,end=' ')

import sys
from collections import defaultdict


def input():
    return sys.stdin.readline().strip()


class UnionFind:
    def __init__(self, n_nodes):
        self.n_nodes = n_nodes
        self.parent = [i for i in range(n_nodes)]
        self.rank = [1] * n_nodes
        self.size = [1] * n_nodes

    def find(self, x):
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.find(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.rank[x] > self.rank[y]:
            self.parent[y] = x
            self.size[x] += self.size[y]
        else:
            self.parent[x] = y
            self.size[y] += self.size[x]
            if self.rank[x] == self.rank[y]:
                self.rank[y] += 1

    def check(self, x, y):
        return self.find(x) == self.find(y)

    def get_parent_list(self):
        return [i for i in range(self.n_nodes) if self.find(i) == i]

    def get_n_groups(self):
        return len(self.get_parent_list())

    def get_members(self, x):
        parent = self.find(x)
        return [i for i in range(self.n_nodes) if self.find(i) == parent]

    def get_members_dict(self):
        return {par: self.get_members(par) for par in self.get_parent_list()}


def main():
    N, K, L = map(int, input().split())
    Tree_road = UnionFind(N)
    Tree_train = UnionFind(N)
    for _ in range(K):
        p, q = map(int, input().split())
        Tree_road.unite(p - 1, q - 1)
    for _ in range(L):
        p, q = map(int, input().split())
        Tree_train.unite(p - 1, q - 1)
    DD = defaultdict(int)
    for i in range(N):
        DD[(Tree_road.find(i), Tree_train.find(i))] += 1
    answer = []
    for i in range(N):
        answer.append(DD[(Tree_road.find(i), Tree_train.find(i))])

    print(*answer, sep=" ")


def __starting_point():
    main()

__starting_point()

import sys
from collections import deque
from collections import defaultdict
from collections import Counter

def conn(n,m,e):
    d=dict(list(zip(list(range(1,n+1)),list(range(-1,(-1)*n-1,-1)))))
    td=defaultdict(lambda:deque([])) #tdは同値類がキーで中の元が値
    c=1
    for edge in e:
        a=edge[0]
        b=edge[1]
        da=d[a] #da,dbはa,bの含まれる同値流のラベル
        db=d[b]
        if da<0 and db<0:
            d[a]=c
            d[b]=c
            td[c].append(a)
            td[c].append(b)
            c+=1
        elif da>0 and db<0:
            d[b]=da
            td[d[a]].append(b)
        elif da<0 and db>0:
            d[a]=db
            td[d[b]].append(a)
        elif da>0 and db>0 and da!=db:
            for x in td[db]:
                d[x]=da
                td[da].append(x)

    return list(d.values())

# def components(n,k,e):
#     ed=defaultdict(lambda:deque())
#     for edge in e:
#         ed[edge[0]].append(edge[1])
#     c=0
#     s=[0]*n
#     label=[0]*n
#     for i in range(1,n+1):
#         if s[i-1]==0:
#             c+=1
#             label[c-1]=c
#             stack=deque([i])
#             while stack:
#                 w=stack.pop()
#                 s[w-1]=c
#                 while ed[w]:
#                     wn=ed[w].pop()
#                     if s[wn-1]==0:
#                         s[wn-1]=c
#                         if ed[wn]:
#                             stack.append(w)
#                             w=wn
#                     elif s[wn-1]<c:
#                         label[s[wn-1]-1]=c
#     print(s)
#     print(label)
#     return [label[s[i]-1] for i in range(n)] 
           
def components(n,k,e):
    ed=defaultdict(lambda:deque())
    for edge in e:
        ed[edge[0]].append(edge[1])
        ed[edge[1]].append(edge[0])
    c=0
    s=[0]*n
    stack=deque()
    for i in range(1,n+1):
        if s[i-1]==0:
            c+=1
            stack.clear()
            stack.append(i)
            while stack:
                w=stack.pop()
                s[w-1]=c
                while ed[w]:
                    wn=ed[w].pop()
                    if s[wn-1]==0:
                        s[wn-1]=c
                        if ed[wn]:
                            stack.append(w)
                            w=wn
    return [s[i] for i in range(n)] 

def components2(n,k,e):
    es=deque(set((edge[0],edge[1])) for edge in e)
    c=0
    s=deque()
    stack=deque()
    while es:
        f=es.pop()
        stack.clear()
        while es:
            l=len(es)
            g=es.pop()
            if g&f:
                f|=g
            else:
                stack.append(g)
            if l==len(stack):
                s.append(f)
                break
            es=stack
    t=[0]*n
    c=0
    while s:
        for x in s.pop():
            t[x-1]=c
        c+=1
    return t
                
                
        
        
def main(n,k,l,e1,e2):
    d1=components(n,k,e1)
    d2=components(n,l,e2)
    p=tuple(zip(iter(d1),iter(d2)))
    d=Counter(p)
    # print(d1,d2,d,p)
    print((' '.join([str(d[x]) for x in p]))) 

def __starting_point():
    ssr=sys.stdin.readline
    n,k,l=list(map(int,ssr().strip().split()))
    e1=[]
    e2=[]
    for _ in range(k):
        e1.append(tuple(map(int,ssr().strip().split())))
    for _ in range(l):
        e2.append(tuple(map(int,ssr().strip().split())))
    main(n,k,l,e1,e2)

__starting_point()

# python 3.4.3
import sys
input = sys.stdin.readline
import numpy as np

# -------------------------------------------------------------
# function
# -------------------------------------------------------------
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0]*(n+1)
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    def check(self, x, y):
        return self.find(x) == self.find(y)

# -------------------------------------------------------------
# main
# -------------------------------------------------------------
N,K,L = map(int,input().split())
PQ = [tuple(map(int,input().split())) for _ in range(K)]
RS = [tuple(map(int,input().split())) for _ in range(L)]

# 道路
A = UnionFind(N)
for p,q in PQ:
    A.unite(p-1,q-1)
 
# 鉄道
B = UnionFind(N)
for r,s in RS:
    B.unite(r-1,s-1)

# 集計
from collections import defaultdict
dic = defaultdict(int)
for i in range(N):
    dic[A.find(i), B.find(i)] += 1
 
Ans = list(dic[A.find(i), B.find(i)] for i in range(N))
print(" ".join(map(str,Ans)))

from collections import defaultdict

N, K, L = list(map(int, input().split()))


# union-findを実装
root_road = [-1] * N
root_train = [-1] * N


def find_road(x):
    if root_road[x] < 0:
        return x

    root_road[x] = find_road(root_road[x])
    return root_road[x]


def union_road(x, y):
    x = find_road(x)
    y = find_road(y)
    if x == y:
        return

    root_road[x] += root_road[y]
    root_road[y] = x


def same_road(x, y):
    return find_road(x) == find_road(y)


def find_train(x):
    if root_train[x] < 0:
        return x

    root_train[x] = find_train(root_train[x])
    return root_train[x]


def union_train(x, y):
    x = find_train(x)
    y = find_train(y)
    if x == y:
        return

    root_train[x] += root_train[y]
    root_train[y] = x


def same_train(x, y):
    return find_train(x) == find_train(y)


dc = defaultdict(list)
dt = defaultdict(list)
for _ in range(K):
    p, q = list(map(int, input().split()))
    p -= 1
    q -= 1
    dc[p].append(q)
    dc[q].append(p)
    union_road(p, q)

for _ in range(L):
    r, s = list(map(int, input().split()))
    r -= 1
    s -= 1
    dt[r].append(s)
    dt[s].append(r)
    union_train(r, s)

# print(root_road, root_train)
dic = {}
for i in range(N):
    if (find_road(i), find_train(i)) not in dic:
        dic[(find_road(i), find_train(i))] = 1
        continue
    else:
        dic[(find_road(i), find_train(i))] += 1

ans = []
for i in range(N):
    ans.append(dic[(find_road(i), find_train(i))])
print((*ans))


class UnionFind:
    def __init__(self, N):
        self.N = N

        # the parent of all node is itself
        # self.parent = list(range(N))
        self.parent = [-1] * N

    def root(self, i):
        if self.parent[i] < 0:
            return i

        r = self.root(self.parent[i])
        self.parent[i] = r
        return r

    def unite(self, i, j):
        i = self.root(i)
        j = self.root(j)

        if i == j:
            return

        if i > j:
            i, j = j, i

        self.parent[i] += self.parent[j]
        self.parent[j] = i
        # print(self.parent)

    def same(self, i, j):
        return self.root(i) == self.root(j)

    def size(self, i):
        return -self.parent[self.root(i)]

    def roots(self):
        return [self.root(i) for i in range(self.N)]

N, K, L = map(int, input().split())

road = UnionFind(N)
rail = UnionFind(N)

for _ in range(K):
    p, q = map(int, input().split())
    p += -1
    q += -1
    road.unite(p, q)

for _ in range(L):
    r, s = map(int, input().split())
    r += -1
    s += -1
    rail.unite(r, s)

pair = {}
for i,j in zip(road.roots(), rail.roots()):
    t = (i, j)

    if t in pair:
        pair[t] += 1
    else:
        pair[t] = 1

ans = ' '.join([str(pair[(i, j)]) for i,j in zip(road.roots(), rail.roots())])
print(ans)

from collections import Counter
from typing import AnyStr


class UnionFind:
    def __init__(self, n):
        self.table = [-1] * n

    def _root(self, x):
        stack = []
        tbl = self.table
        while tbl[x] >= 0:
            stack.append(x)
            x = tbl[x]
        for y in stack:
            tbl[y] = x
        return x

    def find(self, x, y):
        return self._root(x) == self._root(y)

    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.table[r1] += d2
        else:
            self.table[r1] = r2
            self.table[r2] += d1


def main():
    n, k, l = list(map(int, input().split()))
    a = UnionFind(n)
    b = UnionFind(n)
    for _ in range(k):
        p, q = list(map(int, input().split()))
        a.union(p-1, q-1)
    for _ in range(l):
        r, s = list(map(int, input().split()))
        b.union(r-1, s-1)
    pairs = []
    for i in range(n):
        pairs.append((a._root(i), b._root(i)))

    d = Counter(pairs)
    ans = [d[x] for x in pairs]
    print((*ans))


def __starting_point():
    main()

__starting_point()

from collections import defaultdict
import sys
sys.setrecursionlimit(10**9)
input=sys.stdin.readline
N,K,L=map(int,input().split())

def get_par(x):
  if x == par_list[x]:
    return x
  else:
    par_list[x] = get_par(par_list[x])
    return par_list[x]
def merge(x,y):
  par_x = get_par(x)
  par_y = get_par(y)
  if par_x != par_y:
    par_list[par_y] = par_x
def is_same(x,y):
  return get_par(x) == get_par(y)

par_list=list(range(N+1))
for _ in range(K):
  p,q=map(int,input().split())
  merge(p,q)
for i in range(1,N+1):
  par_list[i]=get_par(i)
par_list_road=par_list[:]
  
par_list=list(range(N+1))
for _ in range(L):
  r,s=map(int,input().split())
  merge(r,s)
for i in range(1,N+1):
  par_list[i]=get_par(i)
par_list_rail=par_list[:]

#print(par_list_road)
#print(par_list_rail)
answer_dic=defaultdict(int)
for i in range(1,N+1):
  road_i=par_list_road[i]
  rail_i=par_list_rail[i]
  answer_dic[(road_i,rail_i)]+=1
  
answer_list=[]
for i in range(1,N+1):
  road_i=par_list_road[i]
  rail_i=par_list_rail[i]
  answer_list.append(answer_dic[(road_i,rail_i)])
  
print(*answer_list)

N,K,L = list(map(int, input().split()))

class UnionFind():
    def __init__(self, n):
        # size of n.
        self.n = n
        # n's parent. default is -1.
        self.parents = [-1] * n

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

    def union_merge(self, x, y):
        x = self.find_root(x)
        y = self.find_root(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

    # You shouldn't use these below for optimization.
    # Use only find_root to compare if you need.
    def union_size(self, x):
        # Root value's index has its size with negative.
        return -self.parents[self.find_root(x)]

    def is_same_union(self, x, y):
        return self.find_root(x) == self.find_root(y)

    def same_union_members(self, x):
        root = self.find_root(x)
        return [i for i in range(self.n) if self.find_root(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def union_count(self):
        return len(self.roots())

    def all_unions(self):
        return [self.same_union_members(r) for r in self.roots()]

road = UnionFind(N)
rail = UnionFind(N)

for i in range(K):
    p, k = list(map(int, input().split()))
    road.union_merge(p-1, k-1)

for i in range(L):
    r, s = list(map(int, input().split()))
    rail.union_merge(r-1, s-1)

root_combinations = []
for i in range(N):
    root_combinations.append((road.find_root(i), rail.find_root(i)))

from collections import Counter
same_combinations = Counter(root_combinations)
result = [same_combinations[root_combination] for root_combination in root_combinations]

ans = ' '.join(map(str, result))
print(ans)


class UnionFind:
    def __init__(self,n):
        self.par = [i for i in range(n+1)]  #親のノード番号
        self.rank = [0]*(n+1)
    def find(self,x):  #xの根のノード番号
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    def same_check(self,x,y):  #x,yが同じグループか否か
        return self.find(x) == self.find(y)
    def union(self,x,y):  #x,yの属するグループの併合
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        elif self.rank[x] > self.rank[y]:
            self.par[y] = x
        else:
            self.par[y] = x
            self.rank[x] += 1

N,K,L = map(int,input().split())
A = [list(map(int,input().split())) for i in range(K)]
B = [list(map(int,input().split())) for i in range(L)]

road = UnionFind(N)
train = UnionFind(N)

for i in range(K):
    road.union(A[i][0],A[i][1])
for i in range(L):
    train.union(B[i][0],B[i][1])

pair = [(road.find(i),train.find(i)) for i in range(1,N+1)]

from collections import Counter

#根が同じなら道路or鉄道でつなげる

c = Counter(pair)
print(*[c[i] for i in pair])

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * 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 unite(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

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

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


def renketu(n , k , l , pqli , rsli):

    from collections import defaultdict

    ans = []
    pquf = UnionFind(n)
    rsuf = UnionFind(n)

    [pquf.unite(p - 1 , q - 1) for q , p in pqli]
    [rsuf.unite(r - 1 , s - 1) for r , s in rsli]

    ansdict = defaultdict(int)

    for i in range(n):
        ansdict[(pquf.find(i) , rsuf.find(i))] += 1

    for i in range(n):
        ans.append(ansdict[(pquf.find(i) , rsuf.find(i))])

    return ans

def main():
    n, k, l = map(int, input().split())
    pqli = [list(map(int , input().split())) for i in range(k)]
    rsli = [list(map(int , input().split())) for i in range(l)]
    ans = renketu(n , k , l , pqli , rsli)

    print(*ans)


def __starting_point():
    main()
__starting_point()

from collections import Counter

class UnionFind:
  def __init__(self, n):
    self.n = n
    self.par = [i for i in range(n)]
    self.rank = [0]*n
    
    
  def find(self, x):
    if self.par[x] == x:
      return x
    else:
      self.par[x] = self.find(self.par[x])
      return self.par[x]
  
  
  def unite(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x == y:
      return
    if self.rank[x] < self.rank[y]:
      self.par[x] = y
    else:
      self.par[y] = x
      if self.rank[x] == self.rank[y]:
        self.rank[x] += 1
        
        
  def same(self, x, y):
    return self.find(x) == self.find(y)
  
  
  def members(self, x):
    root = self.find(x)
    return [i for i in range(self.n) if self.find(i) == root]
  

n, k, l  = map(int, input().split())
pq = [list(map(int, input().split())) for i in range(k)]
rs = [list(map(int, input().split())) for i in range(l)]

uf_pq = UnionFind(n)
uf_rs = UnionFind(n)

for p in pq:
  x, y = p
  uf_pq.unite(x-1, y-1)
  
for r in rs:
  x, y = r
  uf_rs.unite(x-1, y-1)
  
pairs = []
for i in range(n):
  pairs.append((uf_pq.find(i), uf_rs.find(i)))
  
count = Counter(pairs)

ans = [count[pair] for pair in pairs]
print(*ans)

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

class UnionFind(object):
    def __init__(self, n):
        self._par = list(range(n))
        self.size = [1] * n
 
    def root(self, v):
        if self._par[v] == v:
            return v
        self._par[v] = self.root(self._par[v])
        return self._par[v]
 
    def unite(self, u, v):
        u, v = self.root(u), self.root(v)
        if u == v:
            return False
        if self.size[u] > self.size[v]:
            u, v = v, u # size[u] <= size[v]
        self.size[v] += self.size[u]
        self._par[u] = v
 
    def is_connected(self, u, v):
        return self.root(u) == self.root(v)


rood = UnionFind(n)
train = UnionFind(n)

for _ in range(k):
    p, q = map(int, input().split())
    rood.unite(p-1, q-1)

for _ in range(l):
    r, s = map(int, input().split())
    train.unite(r-1, s-1)


from collections import Counter
cnt = Counter()
for i in range(n):
    root_r, root_t = rood.root(i), train.root(i)
    cnt[(root_r, root_t)] += 1

ans = []
for i in range(n):
    root_r, root_t = rood.root(i), train.root(i)
    ans.append(cnt[(root_r, root_t)])

print(*ans)

N, K, L = map(int, input().split())
#Parent List(PL)
road = [i for i in range(N)]
rail = [i for i in range(N)]

def fp(x,P): #findParent
    if x == P[x]:
        return x
    else:
        P[x] = fp(P[x],P)
        return P[x]

for i in range(K+L):
    PL = (lambda x:road if x < K else rail)(i)
    p, q = map(lambda x:int(x)-1, input().split())
    p, q = fp(p,PL), fp(q,PL)
    PL[p] = PL[q] = min(p,q)

from collections import defaultdict as dd
Wconnected = dd(lambda:0)
for i in range(N):
    Wconnected[fp(i,road),fp(i,rail)] += 1
print(*[Wconnected[fp(i,road),fp(i,rail)] for i in range(N)])

from collections import deque

def bfs():
    q = deque()
    color1 = [-1] * (n + 1)
    color2 = [-1] * (n + 1)
    for i in range(1, n + 1):
        if color1[i] == -1:
            color1[i] = i
            q.append(i)
            while q:
                p = q.popleft()
                for j in G[p]:
                    if color1[j] == -1:
                        color1[j] = color1[p]
                        q.append(j)
        if color2[i] == -1:
            color2[i] = i
            q.append(i)
            while q:
                p = q.popleft()
                for j in H[p]:
                    if color2[j] == -1:
                        color2[j] = color2[p]
                        q.append(j)
    group = [color1[i] + 200000 * color2[i] for i in range(n + 1)]
    return group

n, k, l = map(int, input().split())
G = [[] for _ in range(n + 1)]
H = [[] for _ in range(n + 1)]
for _ in range(k):
    p, q = map(int, input().split())
    G[p].append(q)
    G[q].append(p)
for _ in range(l):
    r, s = map(int, input().split())
    H[r].append(s)
    H[s].append(r)
group = bfs()
d = {}
for i in range(1, n + 1):
    if group[i] in d:
        d[group[i]] += 1
    else:
        d[group[i]] = 1
ans = [0] * n
for i in range(1, n + 1):
    ans[i - 1] = d[group[i]]
print(" ".join(map(str, ans)))

from collections import Counter
N, K, L = list(map(int, input().split()))
# Union-Find
def get_root(par, node):
  if par[node] == node:
    return node
  root = get_root(par, par[node])
  par[node] = root
  return root

def union(par, rank, a, b):
  root_a, root_b = get_root(par, a), get_root(par, b)
  if root_a == root_b:
    return
  rank_a, rank_b = rank[root_a], rank[root_b]
  if rank_a < rank_b:
    par[root_a] = root_b
  else:
    par[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

par1 = [i for i in range(N)]
rank1 = [1] * N
for _ in range(K):
    a, b = list(map(int, input().split()))
    union(par1, rank1, a-1, b-1)

par2 = [i for i in range(N)]
rank2 = [1] * N
for _ in range(L):
    a, b = list(map(int, input().split()))
    union(par2, rank2, a-1, b-1)

ct = Counter()
for i in range(N):
    a = get_root(par1, i)
    b = get_root(par2, i)
    ct[(a, b)] += 1

print((' '.join([str(ct[(par1[i], par2[i])]) for i in range(N)])))


class UnionFind():
    def __init__(self, n):
        self.parents = [-1] * 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


def main():
    import sys
    from collections import Counter
    # readline = sys.stdin.readline
    readlines = sys.stdin.readlines
    N, K, L = list(map(int, input().split()))
    uf1 = UnionFind(N)
    uf2 = UnionFind(N)

    IN = readlines()
    for i in range(K):
        p, q = list(map(int, IN[i].split()))
        p -= 1; q -= 1
        uf1.union(p, q)
    for j in range(K, K + L):
        r, s = list(map(int, IN[j].split()))
        r -= 1; s -= 1
        # if uf1.find(r) == uf1.find(s):
        uf2.union(r, s)
    
    # ans = []
    # for i in range(N):
    #     ans.append(-uf2.parents[uf2.find(i)])
    # print(*ans)
    path = []
    C = Counter()
    for i in range(N):
        pair = (uf1.find(i), uf2.find(i))
        path.append(pair)
        C[pair] += 1

    ans = []
    for i in range(N):
        ans.append(C[path[i]])
    print((*ans))


def __starting_point():
    main()

__starting_point()

from collections import Counter

n,k,l=map(int,input().split())
city1=[i for i in range(n)]
city2=[i for i in range(n)]

def root(c,x):
  if x==c[x]:
    return x
  else:
    return root(c,c[x])

def union(c,x,y):
  rx=root(c,x)
  ry=root(c,y)
  if rx>ry:
    c[rx]=ry
  else:
    c[ry]=rx

for i in range(k):
  a,b=map(int,input().split())
  union(city1,a-1,b-1)
for i in range(l):
  a,b=map(int,input().split())
  union(city2,a-1,b-1)
r=[]
for i in range(n):
  r.append((root(city1,i),root(city2,i)))
c=Counter(r)
for i in range(n):
  ans=c[r[i]]
  if i==n-1:
    print(ans)
  else:
    print(ans,end=' ')

import sys
from collections import deque
from collections import defaultdict
from collections import Counter

def conn(n,m,e):
    d=dict(list(zip(list(range(1,n+1)),list(range(-1,(-1)*n-1,-1)))))
    td=defaultdict(lambda:deque([])) #tdは同値類がキーで中の元が値
    c=1
    for edge in e:
        a=edge[0]
        b=edge[1]
        da=d[a] #da,dbはa,bの含まれる同値流のラベル
        db=d[b]
        if da<0 and db<0:
            d[a]=c
            d[b]=c
            td[c].append(a)
            td[c].append(b)
            c+=1
        elif da>0 and db<0:
            d[b]=da
            td[d[a]].append(b)
        elif da<0 and db>0:
            d[a]=db
            td[d[b]].append(a)
        elif da>0 and db>0 and da!=db:
            for x in td[db]:
                d[x]=da
                td[da].append(x)

    return list(d.values())

def main(n,k,l,e1,e2):
    d1=conn(n,k,e1)
    d2=conn(n,l,e2)
    p=tuple(zip(iter(d1),iter(d2)))
    d=Counter(p)
    # print(d1,d2,d,p)
    d[(k,l)]=1
    print((' '.join([str(d[x]) for x in p])))

def __starting_point():
    ssr=sys.stdin.readline
    n,k,l=list(map(int,ssr().strip().split()))
    e1=[]
    e2=[]
    for _ in range(k):
        e1.append(tuple(map(int,ssr().strip().split())))
    for _ in range(l):
        e2.append(tuple(map(int,ssr().strip().split())))
    main(n,k,l,e1,e2)

__starting_point()

N, K, L = map(int, input().split())

par = [i for i in range(N)]

def find(x, P):
    if P[x] == x:
        return x
    else:
        b = find(P[x], P)
        P[x] = b
        return b

def unite(x, y, P):
    root_x = find(x, P)
    root_y = find(y, P)
    if root_y > root_x:
        P[root_x] = root_y
    else:
        P[root_y] = root_x

par2 = [i for i in range(N)]

for _ in range(K):
    p, q = map(int, input().split())
    unite(p-1, q-1, par)

for _ in range(L):
    p, q = map(int, input().split())
    unite(p-1, q-1, par2)
#print(par2)

r=[]
for i in range(N):
    r.append((find(i,par), find(i, par2)))

import collections
count = collections.Counter(r)
#print(count)

for i in range(N):
  ans = count[r[i]]
  if i == N-1:
    print(ans)
  else:
    print(ans, end=' ')

"""
道路でつながっているやつが鉄道でもつながっているかどうかを調べるにはどうすればいい？
普通に木ごとのサイズを求めておけばいいのか？

道路ネットワークを根ごとにグルーピングする。その中で、さらに鉄道の根ごとにグルーピングする。
でchooseでペア数を求めれば良い。

"""
import math
import sys
sys.setrecursionlimit(200000)
class UnionFind():
    def __init__(self,n):
        self.parents = [i for i in range(n+1)]

    def find(self,x):
        if self.parents[x] != x:
            self.parents[x] = self.find(self.parents[x])
        return self.parents[x]

    def union(self,x,y):
        self.parents[self.find(y)]=self.find(x)

N,K,L = list(map(int,input().split()))
A = UnionFind(N)
B = UnionFind(N)
for i in range(K):
    p,q = list(map(int,input().split()))
    A.union(p,q)

for i in range(L):
    r,s = list(map(int,input().split()))
    B.union(r,s)


group = {}
for i in range(1,N+1):
    roadRoot = A.find(i)
    if roadRoot not in group:
        group[roadRoot] = {}
    railRoot = B.find(i)
    if railRoot not in group[roadRoot]:
        group[roadRoot][railRoot] = []
    group[roadRoot][railRoot].append(i)

ans = [[]for _ in range(N)]
for i in list(group.items()):
    for j in list(i[1].values()):
        for k in j:
            ans[k-1] = str(len(j))

ans = " ".join(ans)
print(ans)


from collections import Counter

class UnionFind():
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    def find_root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            #経路圧縮
            self.root[x] = self.find_root(self.root[x])
            return self.root[x]
    # 木の併合、入力は併合したい各ノード
    def unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.find_root(x)
        y = self.find_root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    # xとyが同じグループに属するか判断
    def isSame(self, x, y):
        return self.find_root(x) == self.find_root(y)

    # ノードxが属する木のサイズを返す
    def size(self, x):
        return -self.root[self.find_root(x)]
        
n,k,l = map(int,input().split())
fe = UnionFind(n)
bus = UnionFind(n)
for _ in range(k):
    p,q = map(int,input().split())
    fe.unite(p,q)
for _ in range(l):
    r,s = map(int,input().split())
    bus.unite(r,s)
cnt = Counter()
for i in range(1,n+1):
    cnt[fe.find_root(i),bus.find_root(i)] += 1

print(*[cnt[fe.find_root(i),bus.find_root(i)]for i in range(1,n+1)])

from collections import Counter


class Union_Find:
    def __init__(self, n):
        self.par = [-1] * n
        self.siz = [1] * n

    def root(self, x):
        if self.par[x] == -1:
            return x
        else:
            self.par[x] = self.root(self.par[x])
            return self.par[x]

    def issame(self, x, y):
        return self.root(x) == self.root(y)

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)

        if x == y:
            return False

        if self.siz[x] < self.siz[y]:
            tmp = x
            x = y
            y = tmp

        self.par[y] = x
        self.siz[x] += self.siz[y]
        return True

    def size(self, x):
        return self.siz[self.root(x)]


N, K, L = map(int, input().split())
road_uf = Union_Find(N)
train_uf = Union_Find(N)

for _ in range(K):
    p, q = map(int, input().split())
    p -= 1
    q -= 1
    road_uf.unite(p, q)

for _ in range(L):
    r, s = map(int, input().split())
    r -= 1
    s -= 1
    train_uf.unite(r, s)

roots = [''] * N
for i in range(N):
    r = str(road_uf.root(i)) + '-' + str(train_uf.root(i))
    roots[i] = r

counts = Counter(roots)

ans = [1] * N
for i in range(N):
    r = roots[i]
    ans[i] = counts[r]

print(*ans)

#!/usr/bin python3
# -*- coding: utf-8 -*-

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    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

    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 same(self, x, y):       #xとyが同じグループかどうか
        return self.find(x) == self.find(y)

    def size(self, x):          #グループの要素数
        return -self.parents[self.find(x)]

    def members(self, x):       #xと同じグループの要素
        root = self.find(x)
        return {i for i in range(self.n) if self.find(i) == root}

    def roots(self):            #親の要素一覧
        return {i for i, x in enumerate(self.parents) if x < 0}

    def group_count(self):      #グループの個数
        return len(self.roots())

    def all_group_members(self):      #グループのメンバー一覧
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

################

from collections import Counter

def main():
    N, K, L = map(int, input().split())
    ufK = UnionFind(N)
    ufL = UnionFind(N)
    for i in range(K):
        a,b = map(int,input().split())
        ufK.union(a-1, b-1)
    for i in range(L):
        a,b = map(int,input().split())
        ufL.union(a-1, b-1)

    ps=[(ufK.find(i),ufL.find(i)) for i in range(N)]
    cps = Counter(ps)
    ret = [0]*N
    for i in range(N):
        ret[i] =cps[ps[i]]
    print(*ret)

def __starting_point():
    main()
__starting_point()

import sys
from collections import deque
from collections import defaultdict
from collections import Counter

def conn(n,m,e):
    d=dict(list(zip(list(range(1,n+1)),list(range(-1,(-1)*n-1,-1)))))
    td=defaultdict(lambda:deque([])) #tdは同値類がキーで中の元が値
    c=1
    for edge in e:
        a=edge[0]
        b=edge[1]
        da=d[a] #da,dbはa,bの含まれる同値流のラベル
        db=d[b]
        if da<0 and db<0:
            d[a]=c
            d[b]=c
            td[c].append(a)
            td[c].append(b)
            c+=1
        elif da>0 and db<0:
            d[b]=da
            td[d[a]].append(b)
        elif da<0 and db>0:
            d[a]=db
            td[d[b]].append(a)
        elif da>0 and db>0 and da!=db:
            for x in td[db]:
                d[x]=da
                td[da].append(x)

    return list(d.values())

def components(n,k,e):
    ed=defaultdict(lambda:deque())
    for edge in e:
        ed[edge[0]].append(edge[1])
        ed[edge[1]].append(edge[0])
    c=0
    s=[0]*n
    for i in range(1,n+1):
        if s[i-1]==0:
            c+=1
            stack=deque([i])
            while stack:
                w=stack.pop() 
                s[w-1]=c
                while ed[w]:
                    wn=ed[w].pop()
                    if s[wn-1]==0:
                        s[wn-1]=c
                        if ed[wn]:
                            stack.append(w)
                            w=wn
    return s
           
def main(n,k,l,e1,e2):
    d1=components(n,k,e1)
    d2=components(n,l,e2)
    p=tuple(zip(iter(d1),iter(d2)))
    d=Counter(p)
    # print(d1,d2,d,p)
    d[(k,l)]=1
    print((' '.join([str(d[x]) for x in p]))) 

def __starting_point():
    ssr=sys.stdin.readline
    n,k,l=list(map(int,ssr().strip().split()))
    e1=[]
    e2=[]
    for _ in range(k):
        e1.append(tuple(map(int,ssr().strip().split())))
    for _ in range(l):
        e2.append(tuple(map(int,ssr().strip().split())))
    main(n,k,l,e1,e2)

__starting_point()

from collections import Counter
n,k,l=map(int,input().split())
city1=[i for i in range(n)]
city2=[i for i in range(n)]
def root(c,x):
  if x==c[x]:
    return x
  else:
    return root(c,c[x])
def union(c,x,y):
  rx=root(c,x)
  ry=root(c,y)
  if rx>ry:
    c[rx]=ry
  else:
    c[ry]=rx
for i in range(k):
  a,b=map(int,input().split())
  union(city1,a-1,b-1)
for i in range(l):
  a,b=map(int,input().split())
  union(city2,a-1,b-1)
r=[]
for i in range(n):
  r.append((root(city1,i),root(city2,i)))
c=Counter(r)
for i in range(n):
  ans=c[r[i]]
  if i==n-1:
    print(ans)
  else:
    print(ans,end=' ')

from collections import Counter
N,K,L=map(int,input().split())
drive = [-1] * N;train = [-1] * N
def find(List,x):
  if List[x] < 0:
    return x
  List[x] = find(List,List[x])
  return List[x]
def unite(List,x,y):
  if find(List,x) != find(List,y):
    List[find(List,y)] = find(List,x)
for i in range(K+L):
  a, b = map(int,input().split())
  unite(drive if i < K else train,a-1, b-1)
pair = [(find(drive,i), find(train,i)) for i in range(N)]
c =Counter(pair)
print(*[c[pair[i]] for i in range(N)])

from collections import deque, Counter

N, K, L = [int(s) for s in input().split()]
edge_road = [[int(s) - 1 for s in input().split()] for _ in range(K)]
edge_train = [[int(s) - 1 for s in input().split()] for _ in range(L)]
graph_road = [[] for _ in range(N)]
graph_train = [[] for _ in range(N)]

for i, j in edge_road:
    graph_road[i].append(j)
    graph_road[j].append(i)

for i, j in edge_train:
    graph_train[i].append(j)
    graph_train[j].append(i)

group_road = [0] * N
group_num = 0

visited = [False]*N

for i in range(N):
    if visited[i]:
        continue
    dq = deque([i])
    group_road[i] = group_num
    visited[i] = True
    while(dq):
        search_obj = dq.pop()
        for candidate_obj in graph_road[search_obj]:
            if not visited[candidate_obj]:
                group_road[candidate_obj] = group_num
                dq.appendleft(candidate_obj)
                visited[candidate_obj] = True
    group_num += 1


group_train = [0] * N
group_num = 0

visited = [False]*N

for i in range(N):
    if visited[i]:
        continue
    dq = deque([i])
    group_train[i] = group_num
    visited[i] = True
    while(dq):
        search_obj = dq.pop()
        for candidate_obj in graph_train[search_obj]:
            if not visited[candidate_obj]:
                group_train[candidate_obj] = group_num
                dq.appendleft(candidate_obj)
                visited[candidate_obj] = True
    group_num += 1

group_count = Counter(zip(group_road, group_train))

for gr, gt in zip(group_road, group_train):
    print(group_count[(gr, gt)], end=' ')