#include using namespace std; int N, M, K; vector> keep; void print_no() { cout << "No\n"; } void print_yes() { cout << "Yes\n"; for (int u = 1; u <= N; ++u) { for (int v = u + 1; v <= N; ++v) { if (!keep[u][v]) { cout << u << ' ' << v << '\n'; } } } } int main() { cin >> N >> M >> K; int T = N * (N - 1) / 2; int E = T - M; // number of edges to keep keep.assign(N + 1, vector(N + 1, false)); // WRONG: // This solution forgets the special case K == 1. // It always uses the construction for K >= 2. int U = N - K - 1; // number of vertices not on the path int min_keep = K; int max_keep = K + 3 * U + U * (U - 1) / 2; if (!(min_keep <= E && E <= max_keep)) { print_no(); return 0; } // Keep the mandatory path: // 1 - 2 - ... - K - N // // When K == 1, this incorrectly creates only edge (1, N), // but the later "free edge" construction is not valid. for (int i = 1; i < K; ++i) { keep[i][i + 1] = true; E--; } keep[K][N] = true; E--; vector> free_edges; // WRONG when K == 1: // It treats vertices 2,3,...,N-1 as extra vertices // and connects them to 1,2,3, even though K==1 only requires (1,N) to remain. for (int x = K + 1; x <= N - 1; ++x) { free_edges.push_back({1, x}); free_edges.push_back({2, x}); if (K == 2) { free_edges.push_back({x, N}); } else { free_edges.push_back({3, x}); } } // Extra vertices can be connected freely among themselves. for (int x = K + 1; x <= N - 1; ++x) { for (int y = x + 1; y <= N - 1; ++y) { free_edges.push_back({x, y}); } } for (auto [u, v] : free_edges) { if (E == 0) break; if (u > v) swap(u, v); keep[u][v] = true; E--; } print_yes(); return 0; }