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

typedef long long ll;
typedef long double ld;
const long long MOD = 1'000'000'007LL; // 998'244'353LL;
const int INF = 2'000'000'000;

#define FOR(i,a,b)  for(int i=(a); i  < int(b); ++i)
#define FORD(i,a,b) for(int i=(a); i >= int(b); --i)
#define REP(i,n)  FOR(i,0,n)
#define REPD(i,n) FORD(i,n-1,0)
#define ALL(v) (v).begin(), (v).end()

int n,d,k; 
int idx;
vector<pair<int,int>> ans;

void solve2(int v, int depth, int deg, int lim) {
    // 次数オーバー
    if (idx >= n+1) return;
    // 深さオーバー
    if (depth > lim) return;
    // 次数条件から辺を張る余裕があり, 頂点数も余裕があるなら
    for (int i = 0; i < (k - deg) and idx <= n; i++) {
        // 辺を張り, 再帰的に処理
        ans.push_back(make_pair(v, idx));
        idx++;
        solve2(idx-1, depth+1, 1, lim);
    }
}

void solve(){
    cin >> n >> d >> k;

    // 明らかに不可能
    if (d >= n or ( d > 2 and k == 1)) {
        cout << "NO" << endl;
        return;
    }

    // d を満たすように辺を張る
    REP(i,d) ans.push_back(make_pair(i+1, i+2));
    // 直径の, 根の子 から 葉の親 まで順番に, 張れるだけ辺を張っていく
    idx = d + 2;
    REP(i,d-1) solve2(i+2, 0, 2, min(i+1, d-i-1)); 

    if ((int)ans.size() == n-1) {
        cout << "YES" << endl;
        for (auto p : ans) {
            cout << p.first << " " << p.second << endl;
        }
    } else {
        cout << "NO" << endl;
    }
}

int main(){
	cin.tie(0);
   	ios::sync_with_stdio(false);
    solve();
    return 0;
}