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

@(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;
    }
    
    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值