#include <bits/stdc++.h>
using namespace std;
const char nl = '\n';
const int E = 1e5 + 10;
struct dsu {
  vector<int> par;
  dsu(int N) {
    par.resize(N + 1);
    iota(par.begin(), par.end(), 0);
  }
  int find(int x) { return (par[x] == x) ? (x) : (par[x] = find(par[x])); }
  bool check(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return false;
    return true;
  }
  bool merge(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return false;
    if (u > v) swap(u, v);
    par[v] = u;
    return true;
  }
};
int main() {
  int N, n, m;
  cin >> N >> n >> m;
  dsu Di(N), Mo(N);
  for (int i = 0; i < n; i++) {
    int u, v;
    cin >> u >> v;
    Di.merge(u, v);
  }
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    Mo.merge(u, v);
  }
  vector<pair<int, int>> res;
  vector<int> v1, v2;
  for (int i = 1; i <= 1; i++) {
    for (int j = i + 1; j <= N; j++) {
      if (Di.check(i, j) && Mo.check(i, j)) {
        res.push_back({i, j});
        Di.merge(i, j);
        Mo.merge(i, j);
      }
      if (Di.find(j) != 1) v1.push_back(j);
      if (Mo.find(j) != 1) v2.push_back(j);
    }
  }
  cout << N - max(n, m) - 1 << nl;
  while (!v1.empty() && !v2.empty()) {
    if (Di.find(v1.back()) == 1 && Mo.find(v1.back()) == 1) {
      v1.pop_back();
      continue;
    }
    if (Di.find(v2.back()) == 1 && Mo.find(v2.back()) == 1) {
      v2.pop_back();
      continue;
    }
    res.push_back({v1.back(), v2.back()});
    Di.merge(v1.back(), v2.back());
    Mo.merge(v1.back(), v2.back());
  }
  for (auto &[x, y] : res) cout << x << ' ' << y << nl;
}
