void main()
{
    long n, k, l;
    rdVals(n, k, l);

    auto road = UnionFind(n);
    foreach (i; 0 .. k)
    {
        long p, q;
        rdVals(p, q);
        --p, --q;
        road.unite(p, q);
    }

    auto rail = UnionFind(n);
    foreach (i; 0 .. l)
    {
        long r, s;
        rdVals(r, s);
        --r, --s;
        rail.unite(r, s);
    }

    long[Pair] cnt;
    foreach (i; 0 .. n)
    {
        ++cnt[Pair(road.root(i), rail.root(i))];
    }

    foreach (i; 0 .. n)
    {
        cnt[Pair(road.root(i), rail.root(i))].write;
        if (i == n - 1) writeln;
        else " ".write;
    }
}

struct Pair
{
    long a, b;
}

struct UnionFind
{
    long[] par, cnt;

    this(long n)
    {
        par.length = n, cnt.length = n;
        foreach (i; 0 .. n)
        {
            par[i] = i;
        }
        cnt[] = 1L;
    }

    long root(long x)
    {
        if (par[x] == x) return x;
        else return par[x] = root(par[x]);
    }

    bool same(long x, long y)
    {
        return root(x) == root(y);
    }

    void unite(long x, long y)
    {
        x = root(x), y = root(y);
        if (x == y) return;
        if (cnt[x] > cnt[y]) swap(x, y);
        cnt[y] += cnt[x];
        par[x] = y;
    }

    long size(long x)
    {
        return cnt[root(x)];
    }
}

enum long mod = 10^^9 + 7;
enum long inf = 1L << 60;
enum double eps = 1.0e-9;

T rdElem(T = long)()
if (!is(T == struct))
{
    return readln.chomp.to!T;
}

alias rdStr = rdElem!string;
alias rdDchar = rdElem!(dchar[]);

T rdElem(T)()
if (is(T == struct))
{
    T result;
    string[] input = rdRow!string;
    assert(T.tupleof.length == input.length);
    foreach (i, ref x; result.tupleof)
    {
        x = input[i].to!(typeof(x));
    }
    return result;
}

T[] rdRow(T = long)()
{
    return readln.split.to!(T[]);
}

T[] rdCol(T = long)(long col)
{
    return iota(col).map!(x => rdElem!T).array;
}

T[][] rdMat(T = long)(long col)
{
    return iota(col).map!(x => rdRow!T).array;
}

void rdVals(T...)(ref T data)
{
    string[] input = rdRow!string;
    assert(data.length == input.length);
    foreach (i, ref x; data)
    {
        x = input[i].to!(typeof(x));
    }
}

void wrMat(T = long)(T[][] mat)
{
    foreach (row; mat)
    {
        foreach (j, compo; row)
        {
            compo.write;
            if (j == row.length - 1) writeln;
            else " ".write;
        }
    }
}

import std.stdio;
import std.string;
import std.array;
import std.conv;
import std.algorithm;
import std.range;
import std.math;
import std.numeric;
import std.mathspecial;
import std.traits;
import std.container;
import std.functional;
import std.typecons;
import std.ascii;
import std.uni;
import core.bitop;