花d+1个点建一个长度为d的链子,然后每个结点可以建一棵深度为min(i-1,d-i+1)的树【因为这个点距链子两头的最长距离是max(i-1,d-i+1),我们需要保证建的树的叶子结点到链子头的距离不超过d】
就做完了。
那为什么不会出现两个叶子结点连起来超过d的情况呢?原因如下:
我用bfs写的建树,因为dfs写错写mle了。。
1 #include<iostream> 2 #include<vector> 3 #include<map> 4 #include<queue> 5 using namespace std; 6 7 int degree[400005],count,pool,k; 8 vector<pair<int,int> > ans; 9 10 int top;//top是上限层数 11 12 void bfs(int i){//在i的后面加子树 13 //如果depth=0,那加k-2个,其他加k-1个 14 queue<pair<int,int> > q; 15 q.push( make_pair(i,0) ); 16 while(!q.empty()){ 17 if(count==0) break; 18 19 pair<int,int> d = q.front(); q.pop(); 20 int index = d.first,depth=d.second; 21 if(depth==top) continue; 22 if(depth==0){ 23 if(count<=k-2){ 24 for(int i=1;i<=count;i++) { 25 ans.push_back( make_pair(index,++pool) ); 26 q.push( make_pair(pool,depth+1) ); 27 } 28 count=0; 29 } 30 else{ 31 for(int i=1;i<=k-2;i++) { 32 ans.push_back( make_pair(index,++pool) ); 33 q.push( make_pair(pool,depth+1) ); 34 } 35 count-=k-2; 36 } 37 } 38 else{ 39 if(count<=k-1){ 40 for(int i=1;i<=count;i++) { 41 ans.push_back( make_pair(index,++pool) ); 42 q.push( make_pair(pool,depth+1) ); 43 } 44 count=0; 45 } 46 else{ 47 for(int i=1;i<=k-1;i++) { 48 ans.push_back( make_pair(index,++pool) ); 49 q.push( make_pair(pool,depth+1) ); 50 } 51 count-=k-1; 52 } 53 } 54 55 } 56 } 57 58 int main(){ 59 int n,d; cin>>n>>d>>k; 60 61 if(d>=n) { cout<<"NO"; return 0; } 62 for(int i=1;i<=d;i++){//用d+1个点建长度为d的链 63 degree[i]++; degree[i+1]++; 64 if(degree[i]>k || degree[i+1]>k) { cout<<"NO"; return 0; } 65 ans.push_back( make_pair(i,i+1) ); 66 } 67 68 //第二个到第d个节点,每个后面加一棵深度为min(i-1,d-i+1)的树 69 count=n-d-1;//还剩n-d-1个点要放 70 pool=d+1;//加的点编号从d+2开始用 71 72 for(int i=2;i<=d;i++){ 73 top=min(i-1,d-i+1); 74 bfs(i); 75 if(count==0) break; 76 } 77 78 if(count>0) { cout<<"NO"; return 0; } 79 cout<<"YES"<<endl; 80 for(vector<pair<int,int> >::iterator it = ans.begin(); it!=ans.end(); it++){ 81 printf("%d %d\n",it->first,it->second); 82 } 83 84 return 0; 85 }