#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <fstream>
#include <cassert>
#include <cstring>
#include <unordered_set>
#include <unordered_map>
#include <numeric>
#include <ctime>
#include <bitset>
#include <complex>
#include <functional>
#include <random>

using namespace std;

const int N = 1000;

int ind[N][N];

vector<pair<int, int>> apply(vector<pair<int, int>> v, int x) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ind[i][j] = -1;
        }
    }
    vector<pair<int, int>> vecs;
    for (int i = 0; i * i <= x; i++) {
        for (int j = 0; j * j <= x; j++) {
            if (i * i + j * j == x) {
                vecs.push_back({-i, j});
                vecs.push_back({i, -j});
                vecs.push_back({i, j});
                vecs.push_back({-i, -j});
            }
        }
    } 
    int n = (int)v.size();
    for (int i = 0; i < n; i++) {
        ind[v[i].first][v[i].second] = i;
    }
    vector<vector<int>> g(n);
    for (int i = 0; i < n; i++) {
        int f, s;
        tie(f, s) = v[i];
        for (auto t : vecs) {
            int dx, dy;
            tie(dx, dy) = t;
            if (f + dx > N || f + dx < 0) continue;
            if (s + dy > N || s + dy < 0) continue;
            if (ind[f + dx][s + dy] != -1) {
                g[i].push_back(ind[f + dx][s + dy]);
            }
        }
    }
    vector<int> used(n);
    vector<int> cl(n);
    vector<int> lol(2);
    function<void(int, int)> dfs = [&](int cur, int c) {
        used[cur] = 1;
        cl[cur] = c;
        lol[c]++;
        for (auto t : g[cur]) {
            if (!used[t]) {
                dfs(t, c ^ 1);
            }
        }
    };
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs(i, 0);
        }
    }
    int mx = 0;
    if (lol[1] > lol[0]) mx = 1;
    vector<pair<int, int>> tk;
    for (int i = 0; i < n; i++) {
        if (cl[i] == mx) {
            tk.push_back(v[i]);
        }
    }
    return tk;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n;
    cin >> n;
    n *= 2;
    int d1, d2;
    cin >> d1 >> d2;
    if (d1 % 2 < d2 % 2) {
        swap(d1, d2);
    }
    if (d2 % 2 == 1) {
        for (int i = 0; i < n; i += 2) {
            for (int j = 0; j < n; j += 2) {
                cout << i << ' ' << j << endl;
            }
        }
        exit(0);
    }
    vector<pair<int, int>> v;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (d1 % 2) {
                if ((i + j) % 2 == 0) {
                    v.push_back({i, j});
                }
            } else {
                v.push_back({i, j});
            }
        }
    }
    if (d1 % 2 == 0) {
        v = apply(v, d1);
    }
    v = apply(v, d2);
    for (int i = 0; i < n * n / 4; i++) {
        cout << v[i].first << ' ' << v[i].second << '\n';
    }
}   

//============================================================================
// Name        : hoba.cpp :)
// Author      : (O_O Diab) (Why_not) (el 3AQ)
// Version     :
// Copyright   : please, Don't touch me :(
// Description : problem (I) in C++
// MAIN IDEA   : max sum of S(X) + S(S(X)) => 100 so brute force
//============================================================================
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ll long long
#define rw freopen("input.txt","r",stdin),freopen("output.txt","w",stdout);
#define pb push_back
#define F first
#define S second
#define pf push_front
#define lp(i,a,b) for (int i=a;i<=(int)b;++i)
#define lp2(i,a,b) for (int i=a;i>=b;--i)
#define f(x) return cout<<x<<"\n",0
#define pii pair<int,int>
#define pll pair<ll,ll>
#define all(c) c.begin(),c.end()
#define allr(c) c.rbegin(),c.rend()
#define p(x) cout<<#x<<" = { "<<x<<" } \n"
#define vi vector<int>
#define vl vector<ll>
#define vii vector<pii>
#define vll vector<pll>
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define EPS 1e-6
// to convert string to number use int a = stoi(string);
// to convert number to string use string s = to_string(int);
#define FAST ios::sync_with_stdio(0),ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define clr(c,x) memset(c,x,sizeof(c));
using namespace __gnu_pbds;
using namespace std;
const ll INFL = 0x3f3f3f3f3f3f3f3fLL;
const int dx[] = { 0, 1, 0, -1, 1, -1, 1, -1 };
const int dy[] = { 1, 0, -1, 0, 1, -1, -1, 1 };
const int N = 2e5 + 5, mod = (int) 1e9 + 7, INF = 0x3f3f3f3f;
vi vv;
vector<vi> v, vec;
set<int> st;
int ans[N] = { }, comp[N] = { };
bool vis[N] = { };
void dfs(int node) {
	vis[node] = true;
	for (auto u : v[node])
		if (!vis[u])
			dfs(u);
	vv.pb(node);
}
int main() {
#ifdef ONLINE_JUDGE
	FAST
#endif
	int n, k, l;
	cin >> n >> k >> l;
	v.resize(n + 1);
	lp(i,1,k)
	{
		int x, y;
		cin >> x >> y;
		v[x].pb(y);
		v[y].pb(x);
	}
	int cnt = 0;
	lp(i,1,n)
	{
		if (vis[i])
			continue;
		vv.clear();
		dfs(i);
		cnt++;
		for (auto u : vv)
			comp[u] = cnt;
	}
	clr(vis, 0);
	v.clear();
	v.resize(n + 1);
	vec.resize(n + 1);
	lp(i,1,l)
	{
		int x, y;
		cin >> x >> y;
		v[x].pb(y);
		v[y].pb(x);
	}
	lp(i,1,n)
	{
		if (vis[i])
			continue;
		vv.clear();
		dfs(i);
		st.clear();
		for (auto u : vv) {
			vec[comp[u]].pb(u);
			st.insert(comp[u]);
		}
		for (auto u : st) {
			for (auto k : vec[u])
				ans[k] = vec[u].size();
			vec[u].clear();
		}
	}
	lp(i,1,n)
		cout << ans[i] << " ";
	return 0;
}