		import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
			public class Main implements Runnable
			{
				static final long MOD = 1000000007L;
				static final long MOD2 = 1000000009L;
				static class InputReader
				{
					private InputStream stream;
					private byte[] buf = new byte[1024];
					private int curChar;
					private int numChars;
					private SpaceCharFilter filter;
					private BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			 
					public InputReader(InputStream stream)
					{
						this.stream = stream;
					}
					
					public int read()
					{
						if (numChars==-1) 
							throw new InputMismatchException();
						
						if (curChar >= numChars)
						{
							curChar = 0;
							try 
							{
								numChars = stream.read(buf);
							}
							catch (IOException e)
							{
								throw new InputMismatchException();
							}
							
							if(numChars <= 0)				
								return -1;
						}
						return buf[curChar++];
					}
				 
					public String nextLine()
					{
						String str = "";
			            try
			            {
			                str = br.readLine();
			            }
			            catch (IOException e)
			            {
			                e.printStackTrace();
			            }
			            return str;
					}
					public int nextInt()
					{
						int c = read();
						
						while(isSpaceChar(c)) 
							c = read();
						
						int sgn = 1;
						
						if (c == '-') 
						{
							sgn = -1;
							c = read();
						}
						
						int res = 0;
						do 
						{
							if(c<'0'||c>'9') 
								throw new InputMismatchException();
							res *= 10;
							res += c - '0';
							c = read();
						}
						while (!isSpaceChar(c)); 
						
						return res * sgn;
					}
					
					public long nextLong() 
					{
						int c = read();
						while (isSpaceChar(c))
							c = read();
						int sgn = 1;
						if (c == '-') 
						{
							sgn = -1;
							c = read();
						}
						long res = 0;
						
						do 
						{
							if (c < '0' || c > '9')
								throw new InputMismatchException();
							res *= 10;
							res += c - '0';
							c = read();
						}
						while (!isSpaceChar(c));
							return res * sgn;
					}
					
					public double nextDouble() 
					{
						int c = read();
						while (isSpaceChar(c))
							c = read();
						int sgn = 1;
						if (c == '-') 
						{
							sgn = -1;
							c = read();
						}
						double res = 0;
						while (!isSpaceChar(c) && c != '.') 
						{
							if (c == 'e' || c == 'E')
								return res * Math.pow(10, nextInt());
							if (c < '0' || c > '9')
								throw new InputMismatchException();
							res *= 10;
							res += c - '0';
							c = read();
						}
						if (c == '.') 
						{
							c = read();
							double m = 1;
							while (!isSpaceChar(c)) 
							{
								if (c == 'e' || c == 'E')
									return res * Math.pow(10, nextInt());
								if (c < '0' || c > '9')
									throw new InputMismatchException();
								m /= 10;
								res += (c - '0') * m;
								c = read();
							}
						}
						return res * sgn;
					}
					
					public String readString() 
					{
						int c = read();
						while (isSpaceChar(c))
							c = read();
						StringBuilder res = new StringBuilder();
						do 
						{
							res.appendCodePoint(c);
							c = read();
						} 
						while (!isSpaceChar(c));
						
						return res.toString();
					}
				 
					public boolean isSpaceChar(int c) 
					{
						if (filter != null)
							return filter.isSpaceChar(c);
						return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
					}
				 
					public String next() 
					{
						return readString();
					}
					
					public interface SpaceCharFilter 
					{
						public boolean isSpaceChar(int ch);
					}
				}
			 	
				public static void main(String args[]) throws Exception
				{
					new Thread(null, new Main(),"Main",1<<26).start();
				}
				int MAXN = 100001;
				ArrayList<Integer> adj[];
				int V;
				public void run() 
				{
					InputReader sc= new InputReader(System.in);
					PrintWriter w= new PrintWriter(System.out);
					int n = sc.nextInt();
					int d = sc.nextInt();
					int k = sc.nextInt();
					if(k >= n) {
						w.println("NO");
						w.close();
						System.exit(0);
					}
					if(k == 1) {
						if(n == 2 && d == 1) {
							w.println("YES");
							w.println("1 2");
							
						}else {
							w.println("NO");
						}
						w.close();
						System.exit(0);
					}
					adj = new ArrayList[n+1];
					for(int i = 1;i <= n;i++) {
						adj[i] = new ArrayList();
					}
					Queue<Integer> q = new LinkedList();
					for(int i = 1;i <= n;i++) {
						q.add(i);
					}
					bfs(q,d,k);
					w.println("YES");
					for(int i = 1;i <= n;i++) {
						for(Integer key: adj[i]) {
							if(key > i) {
								w.println(i + " " + key);
							}
						}
					}
					w.close();
				}
				boolean[] visited;
				void bfs(Queue<Integer> vals,int d,int k) {
					int[] level = new int[vals.size() + 1];
					Queue<Integer> q = new LinkedList();
					Arrays.fill(level, -1);
					int f = vals.poll();
					level[f] = 0;
					q.add(f);
					int curr = 0;
					int maxLevel = 0;
					boolean first = true;
					while(!q.isEmpty()) {
						int cur = q.poll();
						boolean flag = false;
						for(int i = 0;i < k && vals.size() > d - curr;i++) {
							if(vals.isEmpty()) {
								break;
							}
							int navu = vals.poll();
							adj[cur].add(navu);
							adj[navu].add(cur);
							level[navu] = level[cur]+1;
							if(first) {
								curr = maxLevel + level[navu];
								maxLevel = Math.max(maxLevel,level[cur] + 1);
							}else {
								curr = maxLevel + level[navu];
							}
							if(maxLevel == level[navu]) {
								flag = true;
							}
							q.add(navu);
						}
						if(vals.size() <= d - curr || vals.isEmpty()) {
							if(flag)
								maxLevel = Math.max(maxLevel,level[cur] + 1);
							break;
						}
						maxLevel = Math.max(maxLevel,level[cur] + 1);
						if(first) {
							k--;
							first = false;
						}
					}
					if(curr > d) {
						System.out.println("NO");
						System.exit(0);
					}
					int node = level.length;
					for(int i = 1;i < level.length;i++) {
						if(level[i] == maxLevel) {
							node = i;
							break;
						}
					}
					for(int i = node;i < level.length-1;i++) {
						adj[i].add(i+1);
						adj[i+1].add(i);
					}
					return;
				}
				int cnt=  0;
				void dfsUtil(int a,boolean[] visit) {
					visit[a] = true;
					Iterator<Integer> it = adj[a].iterator();
					while(it.hasNext()) {
						int x = it.next();
						if(!visit[x]) {
							cnt++;
							dfsUtil(x,visit);
						}
					}
				}
				
				String reverse(String a) {
					String navi = "";
					for(int i = a.length()-1;i >= 0;i--) {
						navi += a.charAt(i);
					}
					return navi;
				}
				static boolean isPrime(long n)
			    {
			        // Corner cases
			        if (n <= 1) return false;
			        if (n <= 3) return true;
			     
			        // This is checked so that we can skip 
			        // middle five numbers in below loop
			        if (n % 2 == 0 || n % 3 == 0) return false;
			     
			        for (int i = 5; i * i <= n; i = i + 6)
			            if (n % i == 0 || n % (i + 2) == 0)
			            return false;
			     
			        return true;
			    }
			 
				long count = 0;
				long[][] dist;
				void flydwarShall(int k,int size) {
					for(int i = 0;i < size;i++) {
						for(int j = 0;j < size;j++) {
							if(dist[i][j] > dist[i][k] + dist[k][j]) {
								dist[i][j] = dist[i][k] + dist[k][j];
							}
						}
					}
				}
				Pair[] segTree;
				int[] arr;
				void build(int l,int r,int pos) {
					if(l == r) {
						segTree[pos] = new Pair(1,1,1,arr[l],arr[l],true);
						return;
					}
					int mid = (l + r) >> 1;
					build(l,mid,2*pos+1);
					build(mid+1, r, 2*pos+2);
					segTree[pos] = merge(segTree[2*pos+1], segTree[2*pos+2]);
				}
				Pair merge(Pair p1,Pair p2) {
					if(p1.val1 == 0) {
						return p2;
					}else if(p2.val1 == 0) {
						return p1;
					}
					Pair navi = new Pair();
					navi.val1 = p1.val1;
					navi.val2 = p2.val2;
					if(p1.val2 == p2.val1) {
						navi.max = Math.max(p1.max,p2.max);
						navi.first = p1.first;
						navi.second = p2.second;
						navi.whole = false;
					}else {
						navi.max = Math.max(p1.max,Math.max(p2.max,p1.second + p2.first));
						if(p1.whole && p2.whole) {
							navi.first = p1.first + p2.first;
							navi.second = p1.first + p2.first;
							navi.whole = true;
						}else if(p1.whole) {
							navi.first = p1.first + p2.first;
							navi.second = p2.second;
							navi.whole = false;
						}else if(p2.whole) {
							navi.first = p1.first;
							navi.second = p1.second + p2.first;
							navi.whole = false;
						}else {
							navi.first = p1.first;
							navi.second = p2.second;
							navi.whole = false;
						}
					}
					return navi;
				}
				Pair query(int pos, int l, int r, int start, int end)
				{
				    if(end < l || r < start)
				    {
				        return new Pair(0,0,0,0,0,false);
				    }
				    if(start <= l && r <= end)
				    {
				        // range represented by a node is completely inside the given range
				        return segTree[pos];
				    }
				    // range represented by a node is partially inside and partially outside the given range
				    int mid = (l + r) / 2;
				    Pair p1 = query(2*pos + 1, l, mid, start, end);
				    Pair p2 = query(2*pos+2, mid+1, r, start, end);
				    return merge(p1, p2);
				}
				int bsearch(Integer[] arr,int l,int r,int val) {
					int ind = -1;
					while(l <= r) {
						int mid = (l + r)/2;
						if(arr[mid] <= val) {
							l = mid + 1;
							ind = mid;
						}else {
							r = mid - 1;
						}
					}
					return ind;
				}
				
				
				long modExpo(long a,long pow,long mod) {
					long res = 1;
					while(pow > 0) {
						if(pow % 2 == 1) {
							res = (res * a) % mod;
						}
						pow = pow/2;
						a = (a * a) % mod;
					}
					return res;
				}
				  static long modInverse(long a, long m)
				    {
				        
				       
				            // If a and m are relatively prime, then modulo inverse
				            // is a^(m-2) mode m
				         
				                        return        power(a, m - 2, m);
				        
				    }
				     
				    // To compute x^y under modulo m
				// Iterative Java program to 
				// compute modular power
				
				    static long power(long x, long y,long p)
				    {
				        // Initialize result
				        long res = 1;     
				        
				        // Update x if it is more  
				        // than or equal to p
				        x = x % p; 
				     
				        while (y > 0)
				        {
				            // If y is odd, multiply x
				            // with result
				            if((y & 1)==1)
				                res = (res * x) % p;
				     
				            // y must be even now
				            // y = y / 2
				            y = y >> 1; 
				            x = (x * x) % p; 
				        }
				        return res;
				    }
				static class Temp implements Comparable<Temp>{
					String a;
					int b;
					Temp(String a,int b){
						this.a = a;
						this.b = b;
					}
					@Override
					public int compareTo(Temp t){
						return Integer.compare(t.b,this.b);
					}
				}
				static class Pair implements Comparable<Pair>{
					int first;
					int max;
					int second;
					int val1;
					int val2;
					boolean whole;
					
					Pair (int a,int b,int c,int val1,int val2,boolean whole){
						this.first = a;
						this.max = b;
						this.second = c;
						this.val1= val1;
						this.val2 = val2;
						this.whole = whole;
					}
					Pair(){
						
					}
					public boolean equals(Object o)
					{
						Pair p = (Pair)o;
						return (p.first==first && p.max==max) || (p.first == max && p.first == max);
					}
					public int hashCode()
					{
						return new Long(first).hashCode()*31 + new Long(max).hashCode();
					}
					public int compareTo(Pair p){
						return Long.compare(p.first,this.first);
					}
				}
			
			}