Codeforces 1003E(树的直径)

Codeforces 1003E
题意:要构造一棵$n$个点的直径为$d$,并且每个点度数必须小于等于$k$的树

先将直径连起来,然后从中间开始在直径上拓展树,子树上每个点到直径两端都不可以超过$d$,并且要满足每个点度数必须小于等于$k$。用 DFS 完成拓展子树。算是一个细节题,注意处处当前节点如果达到$n$就马上退出

Codeforces Submission

#include<cstdio> 
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#define ms(i, j) memset(i, j, sizeof i)
#define LL long long
#define db double
using namespace std;
int n, d, k, sz, tot;
pair<int, int> ans[500000 + 5];
void dfs(int curlen, int kidlen, int curu) {
    if (curlen == d) return ;
    for (int i = 1; i <= kidlen; i++) {
        sz++; 
        ans[++tot].first = curu, ans[tot].second = sz;
        if (sz >= n) {
            cout << "YES\n";
            for (int i = 1; i <= tot; i++) printf("%d %d\n", ans[i].first, ans[i].second);
            exit(0);
        }
        dfs(curlen + 1, k - 1, sz);
    }
}
void clean() {}
int solve() {
    clean();
    cin >> n >> d >> k;
    if (n < d + 1) return cout << "NO", 0;
    if (k == 1 && n != 2 && d != 1) return cout << "NO", 0;
    tot = 0, sz = 1;
    for (int i = 1; i < d + 1; i++) ans[++tot].first = sz, sz++, ans[tot].second = sz;
    if (sz >= n) {
        cout << "YES\n";
        for (int i = 1; i <= tot; i++) printf("%d %d\n", ans[i].first, ans[i].second);
        exit(0);
    }
    int l = (d + 1 + 1) / 2, r = (d + 1) / 2 + 1;
    while (1) {
        if (l == 1 || r == d + 1) break;
        dfs(max(l - 1, d + 1 - l), k - 2, l);
        if (l != r) dfs(max(l - 1, d + 1 - l), k - 2, r);
        l--, r++;
    }
    if (sz < n) return cout << "NO", 0; else {
        cout << "YES\n";
        for (int i = 1; i <= tot; i++) printf("%d %d\n", ans[i].first, ans[i].second);
    }
    return 0; 
}
int main() {
    solve();
    return 0;
}
------ 本文结束 ------