传送门
// 题意: 给定一颗树的高度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':' ');
}
}
}
}