#include <bits/stdc++.h>
       
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
       

struct Edge {
  int from, to;
  Edge(){};
  Edge(int from, int to) : from(from), to(to) {}

  void scanFrom(std::istream& strm, int base = 1) {
    strm >> from >> to;
    if (base == 1) --from, --to;
  }

  Edge reverse() const { return Edge(to, from); }
};

inline std::istream& operator>>(std::istream& strm, Edge& t) {
  t.scanFrom(strm);
  return strm;
}
       
       

template <typename T>
struct WeightedEdge {
  int from, to;
  T _weight;
  WeightedEdge(){};
  WeightedEdge(int from, int to, T weight)
      : from(from), to(to), _weight(weight) {}

  void scanFrom(std::istream& strm, int base = 1) {
    strm >> from >> to >> _weight;
    if (base == 1) --from, --to;
  }

  T weight() const { return _weight; }

  WeightedEdge reverse() const { return WeightedEdge(to, from, _weight); }
};

template <typename T>
inline std::istream& operator>>(std::istream& strm, WeightedEdge<T>& t) {
  t.scanFrom(strm);
  return strm;
}

template <typename Edge>
class Digraph {
  int _E, _V;
  vector<vector<Edge>> _adjacencyList;

 public:
  int E() const { return _E; }

  int V() const { return _V; }
  int size() const { return _V; }

  Digraph() : _V(0), _E(0){};
  Digraph(int V, int E = 0) : _V(V), _E(E) { _adjacencyList.resize(V); }

  void addEdge(const Edge& e) {
    _adjacencyList[e.from].push_back(e);
    ++_E;
  }

  void addUndirectedEdge(const Edge& e) {
    _adjacencyList[e.from].push_back(e);
    _adjacencyList[e.to].push_back(e.reverse());
    ++_E;
  }

  void addNode() {
    ++_V;
    _adjacencyList.push_back(vector<Edge>());
  }

  void scanFrom(std::istream& strm, int base = 1) {
    if (_V == 0) strm >> _V;
    if (_E == 0) strm >> _E;
    _adjacencyList.resize(_V);
    for (int i = 0; i < _E; ++i) {
      Edge e;
      e.scanFrom(cin, base);
      assert(0 <= e.from < _V);
      assert(0 <= e.to < _V);
      addEdge(e);
    }
  }

  vector<Edge> operator[](int u) const { return _adjacencyList[u]; }
  vector<vector<Edge>>& adjacencyList() { return _adjacencyList; }
};

template <typename Edge>
inline std::istream& operator>>(std::istream& strm, Digraph<Edge>& t) {
  t.scanFrom(strm);
  return strm;
}

int main() {
  int N, K, L;
  cin >> N >> K >> L;

  vector<pair<int, int>> group(N, make_pair(-1, -1));
  Digraph<Edge> Gk(N), Gl(N);
  for (int i = 0; i < (int)(K); ++i) {
    Edge e;
    cin >> e;
    Gk.addUndirectedEdge(e);
  }
  for (int i = 0; i < (int)(L); ++i) {
    Edge e;
    cin >> e;
    Gl.addUndirectedEdge(e);
  }

  function<void(int, int)> dfsk = [&](int u, int g) {
    group[u].first = g;
    for (Edge& e : Gk[u]) {
      if (group[e.to].first != -1) continue;
      dfsk(e.to, g);
    }
  };

  function<void(int, int)> dfsl = [&](int u, int g) {
    group[u].second = g;
    for (Edge& e : Gl[u]) {
      if (group[e.to].second != -1) continue;
      dfsl(e.to, g);
    }
  };

  for (int i = 0; i < (int)(N); ++i) {
    if (group[i].first == -1) dfsk(i, i);
    if (group[i].second == -1) dfsl(i, i);
  }

  vector<pair<int, int>> sorted(group);
  sort((sorted).begin(), (sorted).end());

  for (int i = 0; i < (int)(N); ++i) {
    auto p = equal_range((sorted).begin(), (sorted).end(), group[i]);
    if (i) cout << " ";
    cout << p.second - p.first;
  }
  cout << endl;

  return 0;
}


Measured memory_bytes: 20020