#include <bits/stdc++.h>
using namespace std;

void print() { cout << endl; }
template <typename Head, typename... Tail>
void print(Head head, Tail... tail) {
    int size = sizeof...(Tail);
    cout << head;
    if (size > 0) {
        cout << " ";
    }
    print(tail...);
}

void print0() {}
template <typename Head, typename... Tail>
void print0(Head head, Tail... tail) {
    cout << head;
    print0(tail...);
}

struct xstruct {
    int val;
};
bool operator<=(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val <= rhs.val;
}
bool operator<(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val < rhs.val;
}
bool operator>=(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val >= rhs.val;
}
bool operator>(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val > rhs.val;
}
bool operator==(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val == rhs.val;
}
bool operator!=(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val != rhs.val;
}
class xunionfind {
   public:
    map<xstruct, xstruct> partition;
    map<xstruct, uint64_t> rank;

    void insert(xstruct x) {
        partition[x] = x;
        rank[x] = 0;
    }
    xstruct find(xstruct x) {
        if (partition[x] == x) {
            return x;
        } else {
            partition[x] = find(partition[x]);
            return partition[x];
        }
    }
    void unite(xstruct x, xstruct y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            return;
        }
        if (rank[x] < rank[y]) {
            partition[x] = y;
        } else {
            partition[y] = x;
            if (rank[x] == rank[y]) {
                rank[x]++;
            }
        }
    }
    bool same(xstruct x, xstruct y) {
        return find(x) == find(y);
    }
};

class iunionfind {
   public:
    vector<uint64_t> partition;
    vector<uint64_t> rank;

    iunionfind(uint64_t n) {
        partition.resize(n);
        rank.resize(n);
        for (uint64_t x = 0; x < n; x++) {
            partition[x] = x;
            rank[x] = 0;
        }
    }
    uint64_t find(uint64_t x) {
        if (partition[x] == x) {
            return x;
        } else {
            partition[x] = find(partition[x]);
            return partition[x];
        }
    }
    void unite(uint64_t x, uint64_t y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            return;
        }
        if (rank[x] < rank[y]) {
            partition[x] = y;
        } else {
            partition[y] = x;
            if (rank[x] == rank[y]) {
                rank[x]++;
            }
        }
    }
    bool same(uint64_t x, uint64_t y) {
        return find(x) == find(y);
    }
};

struct ufnode {
    uint64_t id;
    uint64_t rank;
    int64_t val;
};
class idunionfind {
   public:
    // ufnodeのidフィールドは0からの連続整数とする。任意の構造体をほぼ定数時間でfind可能。
    vector<ufnode*> partition;
    idunionfind(vector<ufnode*>& init) {
        partition.resize(init.size());
        for (uint64_t id = 0; id < init.size(); id++) {
            partition[id] = init[id];
            init[id]->rank = 0;
        }
    }
    ufnode* find(ufnode* x) {
        if (partition[x->id] == x) {
            return x;
        } else {
            partition[x->id] = find(partition[x->id]);
            return partition[x->id];
        }
    }
    void unite(ufnode* x, ufnode* y) {
        x = find(x);
        y = find(y);
        if (x->id == y->id) {
            return;
        }
        if (x->rank < y->rank) {
            partition[x->id] = y;
        } else {
            partition[y->id] = x;
            if (x->rank == y->rank) {
                x->rank++;
            }
        }
    }
    bool same(ufnode* x, ufnode* y) {
        return find(x) == find(y);
    }
};

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

    vector<ufnode*> road_nodes(N);
    vector<ufnode*> rail_nodes(N);
    for (int i = 0; i < N; i++) {
        road_nodes[i] = new ufnode{id : i, rank : 0, val : i};
        rail_nodes[i] = new ufnode{id : i, rank : 0, val : i};
    }
    auto road = new idunionfind(road_nodes);
    auto rail = new idunionfind(rail_nodes);

    for (int i = 0; i < K; i++) {
        int p, q;
        cin >> p >> q;
        road->unite(road_nodes[p - 1], road_nodes[q - 1]);
    }
    for (int i = 0; i < L; i++) {
        int r, s;
        cin >> r >> s;
        rail->unite(rail_nodes[r - 1], rail_nodes[s - 1]);
    }

    map<pair<ufnode*, ufnode*>, uint64_t> cnts;
    for (int i = 0; i < N; i++) {
        auto p = pair<ufnode*, ufnode*>{road->find(road_nodes[i]), rail->find(rail_nodes[i])};
        if (cnts.count(p) == 0) {
            cnts[p] = 0;
        }
        cnts[p]++;
    }
    for (int i = 0; i < N; i++) {
        auto p = pair<ufnode*, ufnode*>{road->find(road_nodes[i]), rail->find(rail_nodes[i])};
        if (i > 0) {
            cout << " ";
        }
        cout << cnts[p];
    }
    cout << endl;
}


Measured memory_bytes: 32688