#include using namespace std; int N, M, K; vector> ans; void print_no() { cout << "No\n"; } void print_yes() { cout << "Yes\n"; for (auto [u, v] : ans) { cout << u << ' ' << v << '\n'; } } int main() { cin >> N >> M >> K; int T = N * (N - 1) / 2; // WRONG: // This solution forgets the special case K == 1. // The following formula and construction are intended for K >= 2. int min_removed = K * (K - 1) / 2 + (N - K - 1) * (K - 2); int max_removed = T - K; if (M < min_removed || M > max_removed) { print_no(); return 0; } // Use the path 1 - 2 - ... - K - N. // For K == 1, this becomes 1 - N, but the layer construction below // is not valid for the intended K >= 2 reasoning. vector path; path.push_back(1); for (int v = 2; v <= K; ++v) { path.push_back(v); } path.push_back(N); vector> is_path_edge(N + 1, vector(N + 1, false)); for (int i = 0; i + 1 < (int)path.size(); ++i) { int a = path[i]; int b = path[i + 1]; if (a > b) swap(a, b); is_path_edge[a][b] = true; } // WRONG for K == 1: // layer[1] is first set to 0, but then layer[N] = K = 1. // Extra vertices 2..N-1 are also put into layer 1. // This construction does not represent "distance exactly 1" correctly. vector layer(N + 1, -1); layer[1] = 0; for (int i = 1; i <= K - 1; ++i) { layer[i + 1] = i; } layer[N] = K; // Make extra vertices belong to layer 1. for (int v = K + 1; v <= N - 1; ++v) { layer[v] = 1; } vector> removed(N + 1, vector(N + 1, false)); // First remove all edges whose layer difference is at least 2. // This is the intended minimum-removal construction for K >= 2. // For K == 1, no such edges exist, so this does not capture the true condition. for (int u = 1; u <= N; ++u) { for (int v = u + 1; v <= N; ++v) { if (abs(layer[u] - layer[v]) >= 2) { removed[u][v] = true; ans.push_back({u, v}); } } } // Remove additional non-path edges arbitrarily until exactly M edges are removed. // Because (1, N) is treated as the only path edge when K == 1, // this code may still output seemingly plausible answers, // but the feasibility check above is wrong for K == 1. for (int u = 1; u <= N && (int)ans.size() < M; ++u) { for (int v = u + 1; v <= N && (int)ans.size() < M; ++v) { if (removed[u][v]) continue; if (is_path_edge[u][v]) continue; removed[u][v] = true; ans.push_back({u, v}); } } if ((int)ans.size() < M) { print_no(); return 0; } print_yes(); return 0; }