#include <assert.h>
#include <limits.h>
#include <math.h>
#include <algorithm>
#include <bitset>
#include <cctype>
#include <complex>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using ll = long long;
using P = std::pair<ll, ll>;

#define rep(i, a, b) for (ll(i) = (a); i < (b); i++)
#define all(i) i.begin(), i.end()
#define debug(i) std::cout << i << "\n"

// const ll MOD = 998244353;
const ll MOD = 1000000007;

// UnionFind
template<class T>
struct UnionFind {
  std::vector<T> uni;
  T num;
  UnionFind(T s) : uni(s, -1), num(s) {}

  //頂点aが所属するグループ
  T root(T a) {
    if (uni[a] < 0) {
      return a;
    }
    return uni[a] = root(uni[a]);
  }

  // a,bをつなげる
  bool connect(T a, T b) {
    a = root(a);
    b = root(b);
    if (a == b) {
      return false;
    }

    if (uni[a] > uni[b]) {
      std::swap(a, b);
    }

    uni[a] += uni[b];
    uni[b] = a;
    return true;
  }

  // a,bが同グループか確認
  bool isConnect(T a, T b) { return root(a) == root(b); }

  // aが属するグループの要素数
  T size(T a) { return -uni[root(a)]; }

  //グループ数を返す
  T groups() {
    std::set<T> b;
    for (T i = 0; i < num; i++) {
      b.insert(root(i));
    }
    return b.size();
  }
};

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  //問題文中の添え字が0-indexか1-indexか確認!

  ll n,k,l;
  std::cin>>n>>k>>l;
  UnionFind<int> load(n),rail(n);
  rep(i,0,k){
    ll a,b;
    std::cin>>a>>b;
    a--;b--;
    load.connect(a,b);
  }
  rep(i,0,l){
    ll a,b;
    std::cin>>a>>b;
    a--;b--;
    rail.connect(a,b);
  }
  std::vector<P> temp1(n),temp2(n);
  rep(i,0,n){
    temp1[i]=P(load.root(i),rail.root(i));
    temp2[i]=P(load.root(i),rail.root(i));
  }
  sort(all(temp1));
  rep(i,0,n){
    auto low=std::lower_bound(all(temp1),temp2[i]);
    auto up=std::upper_bound(all(temp1),temp2[i]);
    std::cout<<up-low<<" ";
  }
  return 0;
}
#define NguyenDangQuan the_author

#include <bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define mset(x, i) memset(x,i,sizeof(x))
#define elif else if
#define heap priority_queue
#define fi first
#define se second
#define pb push_back
#define ld long double
#define ll long long
#define ull unsigned long long
#define task "codejam"
using namespace std;

int typetest;
template<class T>
void read(T &x){
    register int c;
    T neg = 1;
    x = (T)0;
    while ((c = getchar()) <= 47 || c >= 58)
		if(c == '-') neg = -1;
    for (; (c > 47 && c < 58); c = getchar()){
        x = (x << 3) + (x << 1) + (T)(c - 48);
    }
	x *= neg;
}
inline void fastIOfileinput(){
	ios:: sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
//	freopen(task".INP", "r", stdin);
//	freopen(task".OUT", "w", stdout);
//	freopen(task".in", "r", stdin);
//	freopen(task".out", "w", stdout);
	typetest = 0;
}

const int N = 2e5 + 2;
int m, n, k;
vector<int> ker[N], kel[N];
int ltr[N], ltl[N];

void Enter(){
	read(n); read(m); read(k);
	while(m--){
		int a, b;
		read(a); read(b);
		ker[a].pb(b);
		ker[b].pb(a);
	}
	while(k--){
		int a, b;
		read(a); read(b);
		kel[a].pb(b);
		kel[b].pb(a);
	}
}

void BFS(int i, int lt[], vector<int> ke[]){
	++m;
	lt[i] = m;
	queue<int> open;
	open.push(i);
	while(open.size()){
		int c = open.front();
		open.pop();
		for(auto i : ke[c]){
			if((!lt[i]))
				open.push(i), lt[i] = m;
		}
	}
}

void solve(){
	m = 0;
	for(int i = 1; i <= n; ++i)
		if(ltr[i] == 0)
			BFS(i, ltr, ker);
	m = 0;
	for(int i = 1; i <= n; ++i)
		if(ltl[i] == 0)
			BFS(i, ltl, kel);
	map<int, map<int, int> > s;
	for(int i = 1; i <= n; ++i){
		++s[ltr[i]][ltl[i]];
//		cerr << ltr[i] << " " << ltl[i] << "\n";
	}
	for(int i = 1; i <= n; ++i){
		int& v = s[ltr[i]][ltl[i]];
		cout << v << " ";
	}
}

signed main(){
	fastIOfileinput();
	if(typetest){
		int t;
		cin >> t;
		int v = t;
		while(t--){
			Enter();
			cout << "Case #" << v - t << ": ";
			solve();
		}
	}
	else{
		Enter();
		solve();
	}
}
