@(E ACMer)
题意:给出树的节点数,直径和高度,构造出这颗树.
分析:
本题还是wa了一次才ac,考验的是稳定,不要慌着,要让知识系统全面了再动手编码
- 对于长度为 d 的树,显然它的最小高度为d+12 ,这就是一个判读是否可以构成的不等式判断句.
- 然后我们来贪心的构造这颗树,从树的根节点1开始,由它先派生出,树的高度的一条链,然后再由他派生出树的直径减去高度的链.这样直径和高度就是同时满足了,剩下的节点只需要连接在不增加高度和直径的节点上即可.
- 这里需要注意的是极端情况,当直径为1的时候,节点必须只能有两个.(因为这个数据,在比赛成功的时候hack成功了七次…)
- 然后我们来考虑,剩下的节点放在哪里不影响高度和直径.直觉上只需要全部链接在根节点上就不会影响了.但是当高度等于直径的时候,再链接在根节点上就会让直径增长了,所以这种情况应该链接到2节点上(比赛的时候在这里wa了一次).
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;
typedef pair<int, int> pii;
typedef long long ull;
typedef long long ll;
typedef vector<int> vi;
#define xx first
#define yy second
#define rep(i, a, n) for (int i = a; i < n; i++)
#define sa(n) scanf("%d", &(n))
#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;
int main(void) {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
int n, d, h;
while (cin >> n >> d >> h) {
if (h < (d + 1) / 2 || (d == 1 && n != 2 )) {
cout << -1 << endl;
return 0;
}
int cnt = 1;
rep (i, 0, h) {
cout << cnt << " " << cnt + 1 << endl;
cnt++;
}
cnt++;
if (d != h) {
rep (i, 0, d - h) {
if (!i) {
cout << 1 << " " << cnt << endl;
} else {
cout << cnt << " " << cnt + 1 << endl;
cnt++;
}
}
cnt++;
while (cnt <= n) {
cout << 1 << " " << cnt << endl;
cnt++;
}
}
else {
while (cnt <= n) {
cout << 2 << " " << cnt++ << endl;
}
}
}
return 0;
}