#include #include using namespace std; int main() { int n, m, K; cin >> n >> m >> K; m = n * (n - 1) / 2 - m; if (m < K || m > (K - 1) + (n - K + 1) * (n - K) / 2) { cout << "No" << endl; return 0; } vector> used(n, vector(n)); for (int i = 0; i < K - 1; i++) { used[i][i + 1] = true; } for (int i = K - 1; i < n; i++) { for (int j = i + 1; j < n; j++) { if (m > 0) { used[i][j] = true; m--; } } } cout << "Yes" << endl; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (!used[i][j]) { cout << i + 1 << " " << j + 1 << endl; } } } return 0; } // 考察 // // M 辺を「残す」という形で考察を進める。(割と終盤まで誤読したので…) // つまり、事前に M <- N(N-1)/2 - Mという変換をする。 // // (1) K が小さい方から考える // (2) K に対するグラフ表現を試みる // (1) : K = 1 は 1--N があれば何でもいい。1 <= M <= N(N-1)/2 で可能。 // K = 2 は K辺以上はいる。1--Nは削除。K <= M <= N(N-1)/2 - 1で可能。 // K = 3 は 削除辺が単体では決まらないから難しめ。 // // (2) 階層0,1,...,Kを考える。階層0は頂点1だけ。それ以外は1頂点以上。階層Kに頂点Nを含める。 // 隣り合う階層(階層iとi+1)と同じ階層の頂点間だけ辺を張ってよい。 // 階層0->1->…->Kをつなぐパスを1つ以上つくる。 // これで最短距離がちょうどKのケースを過不足なく表現できていそう。 // // 達成可能なMの最小値はKで自明。達成可能なMの最大値は何になるか。 // たぶん階層0~K-1は1頂点で、階層KにN-K頂点あるケースが最大になると思う。 // 以下を証明したらよさそう。 // // 隣り合う2階層が「a頂点, b頂点」の最大ケース。c = a + b とおき c は固定する。 // a, b >= 1 のもとで、a = 1 が最適であることを示せばOK。 // 辺の数の最大値は、 // ab + a(a-1)/2 + b(b-1)/2 = a(c-a) + a(a-1)/2 + (c-a)(c-a-1)/2 // = ac - a^2 + (a^2 - a + c^2 - ac - c - ac + a^2 + a) / 2 // = ac - a^2 + a^2 - ac + (c^2 - c) / 2 // = (c^2 - c) / 2 = c(c - 1) / 2 // なんとaが消去された。考えてみれば当たり前で、これはc頂点の完全グラフに等しい。 // // もう一つ足りない考察に気がついた。全体で何辺使うか?の最適化。 // 階層iでC_i頂点使っているとすると、f(n) = n(n-1)/2として、 // score(C) = f(C_0 + C_1) + f(C_1 + C_2) + ... + f(C_{K-1} + C_K) // が最大の辺の数になる。C_1 ~ C_{K-1} のうちいずれかが2以上のとき、 // score(C)を悪化させずに C_1 ~ C_{K-1} をすべて1のケースに帰着させることができそう。 // C_i >= 2 を満たす最大のi (1 <= i <= K-1) をとる。 // C_iを1減らし、C_{i-1}を1増やすとき、score(C)の変化量はどうなるか。 // before: f(C_{i - 1} + C_{i}) + f(C_{i} + C_{i + 1}) // after: f(C_{i - 1} + C_{i}) + f(C_{i} + C_{i + 1} - 1) // のようになり、それ以外のところは影響しない。f(n)はnが非負なら単調増加なので、 // score(C)は減少する。これを繰り返すと、帰着可能。 // 「階層i-1,i間の頂点数が変わらない」かつ「階層i,i+1間の頂点数が減る」から、 // 全体としては減るという解釈ができる。 // // つまり、頂点1,2,…,K+1を階層0,1,...,Kに配置してパスで結んで、 // 頂点K~Nの間でN-K+1頂点のなかで0辺~完全グラフのいずれかを適当に作ればOK。 // 達成可能な M は K <= M <= (K-1) + (N-K+1)(N-K)/2 になる。 // // この問題は、最短距離がKであることのグラフ表現という典型テクを適用したのち、 // マトロイドっぽいやつ(交換しても悪化しない的なやつ)を適用するタイプの問題に見えた。 // ちょうどMにするというのはオマケで、最大値の考察が肝だと思った。