http://www.elijahqi.win/archives/3921
考慮如何構造這棵樹我們只需要把直徑先構造出來然後在直徑上長毛即可
那麼每個直徑上的點保證他的深度不超過到直徑兩端距離的最小值即可
注意特判一些k=1或者k=2的小數據
#include<bits/stdc++.h>
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) {x=x*10+ch-'0',ch=gc();}
return x*f;
}
const int N=4e5+10;
struct node{
int x,y;
};
vector<node> a;int n,D,k,d[N],now,maxd,lt;
inline void dfs(int x,int dep){
if (dep>maxd) return;
if (x>n) return;vector<int> pd;
while(d[x]&<) pd.push_back(now),--lt,a.push_back((node){x,now}),
--d[now],++now,--d[x];
for (int i=0;i<pd.size();++i) dfs(pd[i],dep+1);
}
int main(){
// freopen("e.in","r",stdin);
n=read();D=read();k=read();
if(n<D+1) {puts("NO");return 0;}
for (int i=1;i<=n;++i) d[i]=k;
for (int i=2;i<=D+1;++i){
--d[i-1];--d[i];a.push_back((node){i-1,i});
}lt=n-D-1;now=D+2;
for (int i=1;i<=D+1;++i) if(d[i]<0) {puts("NO");return 0;}
for (int i=2;i<=D;++i){
if(!lt) break;maxd=min(i-1,D+1-i);
dfs(i,1);
}
if (lt) {puts("NO");return 0;}
puts("YES");
for (int i=0;i<a.size();++i) printf("%d %d\n",a[i].x,a[i].y);
return 0;
}