#include using namespace std; int N, M, K; int calc_dist(const vector>& removed_edges) { vector> removed(N + 1, vector(N + 1, false)); for (auto [u, v] : removed_edges) { if (u > v) swap(u, v); removed[u][v] = true; } vector> G(N + 1); for (int u = 1; u <= N; ++u) { for (int v = u + 1; v <= N; ++v) { if (removed[u][v]) continue; G[u].push_back(v); G[v].push_back(u); } } vector dist(N + 1, -1); queue q; dist[1] = 0; q.push(1); while (!q.empty()) { int v = q.front(); q.pop(); for (int to : G[v]) { if (dist[to] != -1) continue; dist[to] = dist[v] + 1; q.push(to); } } return dist[N]; } int main() { cin >> N >> M >> K; int T = N * (N - 1) / 2; vector> is_path_edge(N + 1, vector(N + 1, false)); // Fix the path 1 - 2 - ... - K - N. for (int i = 1; i < K; ++i) { is_path_edge[i][i + 1] = true; } is_path_edge[K][N] = true; vector> candidates; // Only non-path edges are candidates for deletion. for (int u = 1; u <= N; ++u) { for (int v = u + 1; v <= N; ++v) { if (is_path_edge[u][v]) continue; candidates.push_back({u, v}); } } // If even all non-path edges are not enough, output No. if ((int)candidates.size() < M) { cout << "No\n"; return 0; } mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count()); const double TIME_LIMIT = 1.8; auto start = chrono::steady_clock::now(); while (true) { auto now = chrono::steady_clock::now(); double elapsed = chrono::duration(now - start).count(); if (elapsed > TIME_LIMIT) { cout << "No\n"; return 0; } shuffle(candidates.begin(), candidates.end(), rng); vector> removed_edges; for (int i = 0; i < M; ++i) { removed_edges.push_back(candidates[i]); } if (calc_dist(removed_edges) == K) { cout << "Yes\n"; for (auto [u, v] : removed_edges) { cout << u << ' ' << v << '\n'; } return 0; } } }