Codeforces 658 C. Bear and Forgotten Tree 3(树的构造)

@(E ACMer)


题意:给出树的节点数,直径和高度,构造出这颗树.
分析:

本题还是wa了一次才ac,考验的是稳定,不要慌着,要让知识系统全面了再动手编码
- 对于长度为 d 的树,显然它的最小高度为 d+12 ,这就是一个判读是否可以构成的不等式判断句.
- 然后我们来贪心的构造这颗树,从树的根节点1开始,由它先派生出,树的高度的一条链,然后再由他派生出树的直径减去高度的链.这样直径和高度就是同时满足了,剩下的节点只需要连接在不增加高度和直径的节点上即可.
- 这里需要注意的是极端情况,当直径为1的时候,节点必须只能有两个.(因为这个数据,在比赛成功的时候hack成功了七次…)

  • 然后我们来考虑,剩下的节点放在哪里不影响高度和直径.直觉上只需要全部链接在根节点上就不会影响了.但是当高度等于直径的时候,再链接在根节点上就会让直径增长了,所以这种情况应该链接到2节点上(比赛的时候在这里wa了一次).

code:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(ACM_图论,ACM_易错题)