var line = readline ();
line = line.trim ().split ( ' ' );
n = (+ line [ 0 ]);
d = (+ line [ 1 ]);
k = (+ line [ 2 ]);
var n_ = n;
var n, d, k;
var v, curr, path;
if ( n == 2 ) { path = 1; }
else { path = 2; }
curr = 1;
v = 1;
var graph = { };
var other = { };
graph [ curr ] = { };
other [ curr ] = { };
var bb = 0;
var queue = [ ];
var elem = curr;
n --;
aa: while ( n > 0 ) {
    if ( v - curr < k ) {
        v ++;
        graph [ elem ][ v ] = 1;
        if ( ! ( elem in other ) ) other [ elem ] = { };
        other [ elem ][ v ] = 1;
        if ( ! ( v in other ) ) other [ v ] = { };
        other [ (+ v) ][ (+ elem) ] = 1;
        queue.push ( v );
        n --;
    } else {
        curr = v;
        elem = queue.shift ();
        path ++;
        if ( ! ( elem in graph ) ) graph [ elem ] = { };
        if ( ! ( elem in graph ) ) other [ elem ] = { };
        if ( ! bb ) {
            bb = 1;
            k --;
        }
    }
}
var visit = { };
function dfs ( curr ) {
    if ( curr in visit ) return 0;
    visit [ curr ] = 1;
    var z, mx = 1;
    for ( var g in (other [ curr ]) ) {
        z = (+ dfs ( g ));
        z ++;
        if ( z > mx ) mx = z;
    }
    return mx;
}
// call dfs from last vertex because we know that 
// it will be a leaf
path = dfs ( n_ );
path --; // count edges instead of vertices
if ( path > d ) { print ( 'NO' ); }
else { print ( 'YES' );
    var h, g;
    for ( h in graph ) 
        for ( g in graph [ h ] ) 
            print ( h + ' ' + g );
}
function p ( a ) { print ( a ); }
