Codeforces Round #453 (Div. 2) C 题 Hashing Trees

传送门
// 题意: 给定一颗树的高度h, 在给定h+1个数字, 代表每一层上面的节点数, 问是否只有一颗树满足这个序列, 如果是输出perfect , 否则输出ambiguous,并任意给出两组满足这个序列的树的形态. 两棵树同构的概念是如果对于每一个序列中的数它对应的父节点都是一样的, 那么这两棵树同构.

// 思路: 首先判断是否是有一棵树满足这个序列, 从样例二我们就可以很清楚的看出来, 从第二层开始, 如果有连续的两层的节点数同时大于2, 那么就肯定不是perfect的, 下面考虑如果输出两个序列, 我们直接在不是不满足条件的那两层下手就行啦, 我们让(不满足条件的两层分别叫第一层和第二层), 第二层的第一个节点连上第一层的第一个节点, 然后让第二层的剩余节点连第一层的最后一个结点(因为好写), 然后后其他的按照规则连上就行啦

AC Code

const int maxn = 1e5+5;
int a[maxn];
int ans1[maxn<<1], ans2[maxn<<1];
void solve()
{
    int h;
    while(cin >> h) {
        for (int i = 1 ; i <= h + 1 ; i++) {
            cin >> a[i];
        }
        int flag = 1, pos = 2;
        for (int i = 3 ; i <= h+1 ; i ++) {
            if (a[i-1] >= 2 && a[i] >= 2) {
                flag = 0;
                pos = i;
                break;
            }
        }
        if (flag) cout << "perfect" <<endl;
        else {
            cout << "ambiguous" <<endl;
            int k = 1, cnt = 1;
            for (int i = 2 ; i <= h + 1 ; i++) {
                if (i == pos ) {
                    ans1[++cnt] = k-1;
                    for (int j = 2 ; j <= a[i] ; j ++) {
                        ans1[++cnt] = k;
                    }
                }
                else {
                    for (int j = 1 ; j <= a[i] ; j ++) {
                        ans1[++cnt] = k;
                    }
                }
                k += a[i];
            }
            k = 1, cnt = 1;
            for (int i = 2 ; i <= h + 1 ; i++) {
                for (int j = 1 ; j <= a[i] ; j ++) {
                    ans2[++cnt] = k;
                }
                k += a[i];
            }
            for (int i = 1 ; i <= cnt ; i ++) {
                printf("%d%c", ans1[i], i == cnt ?'\n':' ');
            }
            for (int i = 1 ; i <= cnt ; i ++) {
                printf("%d%c", ans2[i], i == cnt ?'\n':' ');
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值