#ifdef DEBUG
#  define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include "testlib.h"
#define ff first
#define ss second
#define szof(x) ((int)x.size())
#ifndef LOCAL
#  define cerr __get_ce
#endif

using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef unsigned long long ull;

using namespace __gnu_pbds;
template <typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename K, typename V> using ordered_map = tree<K, V, less<K>, rb_tree_tag, tree_order_statistics_node_update>;

int const INF = (int)1e9 + 1e3;
ll const INFL = (ll)1e18 + 1e6;

int main(int argc, char* argv[]) {
  registerGen(argc, argv, 1);

  int n = opt<int>("n");
  int m = opt<int>("m");
  int a = opt<int>("a");
  int b = opt<int>("b");

  int x = rnd.next(n);
  set<pair<int, int>> s;
  for (int i = 0; i < a; i++) {
    int u, v;
    do {
      u = x;
      v = rnd.next(n);
    } while (u == v || s.find(make_pair(u, v)) != s.end());
    s.emplace(u, v);
  }
  for (int i = 0; i < b; i++) {
    int u, v;
    do {
      u = rnd.next(n);
      v = x;
    } while (u == v || s.find(make_pair(u, v)) != s.end());
    s.emplace(u, v);
  }
  for (int i = 0; i < m - a - b; i++) {
    int u, v;
    do {
      u = rnd.next(n);
      v = rnd.next(n);
    } while (u == v || s.find(make_pair(u, v)) != s.end());
    s.emplace(u, v);
  }
  assert(int(s.size()) == m);
  vector<pair<int, int>> e(s.begin(), s.end());
  shuffle(e.begin(), e.end());
  cout << 1 << '\n';
  cout << n << " " << m << '\n';
  for (auto& [u, v] : e) {
    cout << u + 1 << " " << v + 1 << '\n';
  }
  return 0;
}