【题解】CF746G New Roads

版权声明:Powered By Fighter https://blog.csdn.net/qq_30115697/article/details/87856109

CF746G New Roads

题意

​ 给你一棵 t t 层的树,第 i i 层有 a [ i ] a[i] 个节点,最后需要有 k k 个叶子结点,让你构造出一棵符合条件的树。

解题思路

​ 我们可以先构造出 t t 层,每层只有一个节点,父亲是上一层的节点。那么显然此时剩余的节点数为 n t n-t 。剩余所需的非叶子节点的数量为 n t k n-t-k 。于是我们可以逐层插入节点,并对这些节点分类讨论。设此时已经插入到第 i i 层的第 j j 个点。如果此时还需要非叶子节点,那么它的父亲就可以是第 i 1 i-1 层的第 j j 个,这样它的父亲就变为了非叶子节点;反之,如果不需要非叶子节点,直接用上一层的第一个节点当做它的父亲,那么上一层当前位置的节点就成为了叶子结点。

​ 对于无解的判断,无非就是最末层的节点数大于 k k ,因为最后一层的节点必定是叶子结点。或者在构造完之后还需要非叶子节点,但此时已经没有可以构造的叶子节点了。

代码

#include <bits/stdc++.h>
using namespace std;

int n, t, k, cnt;
vector<int> v[200005];
int a[200005], fa[200005];

int main()
{
    cin >> n >> t >> k;
    a[0] = 1;
    for(int i = 1; i <= t; i++){
        scanf("%d", &a[i]);
    }
    if(a[t]>k || n-t<k){
        puts("-1");
        return 0;
    }
    for(int i = 0; i <= t; i++){
        for(int j = 1; j <= a[i]; j++)
            v[i].push_back(++cnt);
    }
    for(int i = 0; i < a[1]; i++){
        fa[v[1][i]] = 1;
    }
    for(int i = 2; i <= t; i++){
        fa[v[i][0]] = v[i-1][0];
    }
    int l = n-t-k;
    for(int i = 2; i <= t; i++){
        for(int j = 1; j < a[i]; j++){
            if(l && j < a[i-1]){
                fa[v[i][j]] = v[i-1][j];
                l--;
            }
            else{
                fa[v[i][j]] = v[i-1][0];
            }
        }
    }
    if(l){
        puts("-1");
        return 0;
    }
    cout << n << endl;
    for(int i = 2; i <= n; i++){
        printf("%d %d\n", fa[i], i);
    }
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30115697/article/details/87856109