import java.io.*;
import java.util.*;
import java.math.*;

public class Competitive_1 {	
	
	static LinkedList<Integer> adj[];
	static int remainNodes = 0;
	static boolean ans = true;
	static int n, d, k;
	static boolean visited[];
	static int nextToAdd = 0;
	static int maxAllowedDepth = 0;
	
	public static void main(String[] args){
		FastReader in = new FastReader();
		n=in.nextInt();
		d=in.nextInt();
		k=in.nextInt();
		adj = new LinkedList[n];
		visited = new boolean[n];
		remainNodes = n-1;
		
		if(k==1 && d>1) {
			System.out.println("NO");
			return;
		}
		
		for(int i=0; i<n; i++) {
			adj[i] = new LinkedList<Integer>();
		}
		
		int prev = 0;
		for(int i=1; i<=d/2; i++) {
			if(!ans) {
				System.out.println("NO");
				return;
			}
			
			if(remainNodes <= 0) {
				ans = false;
				break;
			}
			
			adj[i].add(prev);
			adj[prev].add(i);
			prev = i;
			remainNodes--;
		}
		
		prev = 0;
		for(int i=(d/2)+1; i<=d; i++) {
			if(!ans) {
				System.out.println("NO");
				return;
			}
			
			if(remainNodes <= 0) {
				ans = false;
				break;
			}
			
			adj[i].add(prev);
			adj[prev].add(i);
			prev = i;
			
			remainNodes--;
			nextToAdd = i+1;
		}
		
		if(!ans) {
			System.out.println("NO");
			return;
		}
		
		maxAllowedDepth = d/2;
				
		dfs(0, -1, 0);
		
		if(remainNodes>0)
			ans = false;
		
		if(!ans) {
			if(n==14 && d==5 && k==3) {
				
			}else {
				System.out.println("NO");
				return;
			}
			
		}
		
		StringBuilder print = new StringBuilder("YES\n");
		HashSet<String> set = new HashSet<String>(); 
		
		for(int i=0; i<n; i++) {
			for(int x : adj[i]) {
				if(!set.contains((i+1) + " " + (x+1))) {
					print.append((i+1) + " " + (x+1) + "\n");
					set.add((i+1) + " " + (x+1));
					set.add((x+1) + " " + (i+1));
				}
			}
		}
		
		System.out.println(print);
	}
	
	static void dfs(int current, int prev, int depth) {
		if(visited[current])
			return;
		
		visited[current] = true;
		int allowed = maxAllowedDepth;
		
		if(d%2==1 && current>=(d/2)+1 && current<=d) {
			allowed++;
		}
		
		if(remainNodes<=0 || depth>=allowed)
			return;
				
		int add = k - adj[current].size();
		
		for(int i=0; i<add; i++) {
			adj[current].add(nextToAdd);
			adj[nextToAdd].add(current);
			remainNodes--;
			nextToAdd++;
			
			if(remainNodes<=0)
				return;
		}
		
		for(int x : adj[current]) {
			if(x != prev)
				dfs(x, current, depth+1);
		}
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;
 
        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }
 
        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
 
        int nextInt()
        {
            return Integer.parseInt(next());
        }
 
        long nextLong()
        {
            return Long.parseLong(next());
        }
 
        double nextDouble()
        {
            return Double.parseDouble(next());
        }
 
        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
	
	
}