题意:构造一个直径为d 每个点的度数不超过k的树 (注意直径必须为d 而不是不大于d)
思路:
先构造一个直径 即1-2 2-3 ... d-d+1
然后放入队列中,每次拿出来一个点,判断这个点是否能再放点( 度数是否满 是否是叶子节点)
而且还要保存每一个点在这个树中的位置 为1就是叶子节点
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <queue>
#include <iostream>
#define ll long long
#define INF 0x3f3f3f
using namespace std;
const int N=1000000+100;
struct node
{
int pos,du,id;
}p[N],now,nextt;
queue <node> q;
vector <int> v[N];
int main()
{
int n,d,k,i,j,st,dd;
scanf("%d%d%d",&n,&dd,&k);
d=dd+1;
for(i=1;i<=d;i++)
{
p[i].id=i;
if(i==1 || i==d)
{
p[i].pos=1;
p[i].du=1;
}
else
{
if(i > (d+1)/2) p[i].pos=d-i+1;
else p[i].pos=i;
p[i].du=2;
q.push(p[i]);
}
}
for(i=1;i<d;i++)
v[i].push_back(i+1);
st=d+1;
while(!q.empty())
{
if(st>n) break;
now=q.front();
q.pop();
if(now.du==k || now.pos==1) continue;
nextt.du=1;nextt.pos=now.pos-1;nextt.id=st;
q.push(nextt);
nextt.du=now.du+1;nextt.pos=now.pos;nextt.id=now.id;
q.push(nextt);
v[now.id].push_back(st++);
}
if(d>n || st<=n || k==1&&n>2 )printf("NO\n");
else
{
printf("YES\n");
for(i=1;i<=n;i++)
for(j=0;j<v[i].size();j++)
printf("%d %d\n",i,v[i][j]);
}
return 0;
}